xref: /plan9-contrib/sys/src/cmd/db/expr.c (revision 3e12c5d1bb89fc02707907988834ef147769ddaf)
1 /*
2  *
3  *	debugger
4  *
5  */
6 
7 #include "defs.h"
8 #include "fns.h"
9 
10 static long	round(long, long);
11 
12 WORD	var[NVARS];
13 
14 extern	char	lastc, peekc;
15 
16 extern	ADDR	ditto;
17 extern	int	ditsp;
18 WORD	expv;
19 int	expsp;
20 
21 WORD
22 defval(WORD w)
23 {
24 	if (expr(0))
25 		return (expv);
26 	else
27 		return (w);
28 }
29 
30 expr(int a)
31 {	/* term | term dyadic expr |  */
32 	int	rc;
33 	WORD	lhs;
34 
35 	rdc();
36 	reread();
37 	expsp = SEGNONE;
38 	rc=term(a);
39 	while (rc) {
40 		lhs = expv;
41 		switch ((int)readchar()) {
42 
43 		case '+':
44 			term(a|1);
45 			expv += lhs;
46 			break;
47 
48 		case '-':
49 			term(a|1);
50 			expv = lhs - expv;
51 			break;
52 
53 		case '#':
54 			term(a|1);
55 			expv = round(lhs,expv);
56 			break;
57 
58 		case '*':
59 			term(a|1);
60 			expv *= lhs;
61 			break;
62 
63 		case '%':
64 			term(a|1);
65 			if(expv != 0)
66 				expv = lhs/expv;
67 			else{
68 				if(lhs)
69 					expv = 1;
70 				else
71 					expv = 0;
72 			}
73 			break;
74 
75 		case '&':
76 			term(a|1);
77 			expv &= lhs;
78 			break;
79 
80 		case '|':
81 			term(a|1);
82 			expv |= lhs;
83 			break;
84 
85 		case ')':
86 			if ((a&2)==0)
87 				error("unexpected `)'");
88 
89 		default:
90 			reread();
91 			return(rc);
92 		}
93 	}
94 	return(rc);
95 }
96 
97 term(int a)
98 {	/* item | monadic item | (expr) | */
99 
100 	switch ((int)readchar()) {
101 
102 	case '*':
103 		term(a|1);
104 		get4(cormap, (ADDR)expv, SEGDATA, &expv);
105 		expsp = SEGNONE;
106 		chkerr();
107 		return(1);
108 
109 	case '@':
110 		term(a|1);
111 		get4(symmap, (ADDR)expv, SEGTEXT, &expv);
112 		expsp = SEGNONE;
113 		return(1);
114 
115 	case '-':
116 		term(a|1);
117 		expv = -expv;
118 		return(1);
119 
120 	case '~':
121 		term(a|1);
122 		expv = ~expv;
123 		return(1);
124 
125 	case '(':
126 		expr(2);
127 		if (readchar()!=')')
128 			error("syntax error: `)' expected");
129 		return(1);
130 
131 	case '%':
132 		term(a|1);
133 		expsp = SEGREGS;
134 		return(1);
135 
136 	default:
137 		reread();
138 		return(item(a));
139 	}
140 }
141 
142 item(int a)
143 {	/* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
144 	int	base;
145 	char	savc;
146 	Symbol s;
147 	char gsym[MAXSYM], lsym[MAXSYM];
148 
149 	readchar();
150 	if (isfileref()) {
151 		readfname(gsym);
152 		rdc();			/* skip white space */
153 		if (lastc == ':') {	/* it better be */
154 			rdc();		/* skip white space */
155 			if (!getnum(readchar))
156 				error("bad number");
157 			if (expv == 0)
158 				expv = 1;	/* file begins at line 1 */
159 			expv = file2pc(gsym, expv);
160 			if (expv == -1)
161 				error(symerror);
162 			expsp = SEGNONE;
163 			return 1;
164 		}
165 		error("bad file location");
166 	} else if (symchar(0)) {
167 		readsym(gsym);
168 		if (lastc=='.') {
169 			readchar();	/* ugh */
170 			if (!symchar(0))
171 				localaddr(gsym, 0);
172 			else {
173 				readsym(lsym);
174 				localaddr(gsym, lsym);
175 			}
176 		}
177 		else {
178 			if (lookup(0, gsym, &s) == 0)
179 				error("symbol not found");
180 			expv = s.value;
181 		}
182 		reread();
183 	} else if (getnum(readchar)) {
184 		;
185 	} else if (lastc=='.') {
186 		readchar();
187 		if (!symchar(0)) {
188 			expv = dot;
189 			expsp = dotsp;
190 		} else {
191 			readsym(lsym);
192 			localaddr(0, lsym);
193 		}
194 		reread();
195 	} else if (lastc=='"') {
196 		expv=ditto;
197 		expsp = ditsp;
198 	} else if (lastc=='+') {
199 		expv=inkdot(dotinc);
200 		expsp = ditsp;
201 	} else if (lastc=='^') {
202 		expv=inkdot(-dotinc);
203 		expsp = ditsp;
204 	} else if (lastc=='<') {
205 		savc=rdc();
206 		base = getreg(savc);
207 		if (base != BADREG)
208 			expv = rget(base);
209 		else if ((base = varchk(savc)) != -1)
210 			expv = var[base];
211 		else
212 			error("bad variable");
213 	}
214 	else if (lastc=='\'')
215 		expv = ascval();
216 	else if (a)
217 		error("address expected");
218 	else {
219 		reread();
220 		return(0);
221 	}
222 	return(1);
223 }
224 
225 #define	MAXBASE	16
226 
227 /* service routines for expression reading */
228 getnum(int (*rdf)(void))
229 {
230 	char *cp;
231 	int base, d;
232 	BOOL fpnum;
233 	char num[MAXLIN];
234 
235 	base = 0;
236 	fpnum = FALSE;
237 	if (lastc == '#') {
238 		base = 16;
239 		(*rdf)();
240 	}
241 	if (convdig(lastc) >= MAXBASE)
242 		return (0);
243 	if (lastc == '0')
244 		switch ((*rdf)()) {
245 		case 'x':
246 		case 'X':
247 			base = 16;
248 			(*rdf)();
249 			break;
250 
251 		case 't':
252 		case 'T':
253 			base = 10;
254 			(*rdf)();
255 			break;
256 
257 		case 'o':
258 		case 'O':
259 			base = 8;
260 			(*rdf)();
261 			break;
262 		default:
263 			if (base == 0)
264 				base = 8;
265 			break;
266 		}
267 	if (base == 0)
268 		base = 10;
269 	expv = 0;
270 	for (cp = num, *cp = lastc; ;(*rdf)()) {
271 		if ((d = convdig(lastc)) < base) {
272 			expv *= base;
273 			expv += d;
274 			*cp++ = lastc;
275 		}
276 		else if (lastc == '.') {
277 			fpnum = TRUE;
278 			*cp++ = lastc;
279 		} else {
280 			reread();
281 			break;
282 		}
283 	}
284 	if (fpnum)
285 		expv = fpin(num);
286 	return (1);
287 }
288 
289 void
290 readsym(char *isymbol)
291 {
292 	char	*p;
293 
294 	p = isymbol;
295 	do {
296 		if (p < &isymbol[MAXSYM-1])
297 			*p++ = lastc;
298 		readchar();
299 	} while (symchar(1));
300 	*p = 0;
301 }
302 
303 void
304 readfname(char *filename)
305 {
306 	char	*p;
307 	char	c;
308 
309 	/* snarf chars until un-escaped char in terminal char set */
310 	p = filename;
311 	do {
312 		if ((c = lastc) != '\\' && p < &filename[MAXSYM-1])
313 			*p++ = c;
314 		readchar();
315 	} while (c == '\\' || strchr(CMD_VERBS, lastc) == 0);
316 	*p = 0;
317 	reread();
318 }
319 
320 convdig(int c)
321 {
322 	if (isdigit(c))
323 		return(c-'0');
324 	else if (!isxdigit(c))
325 		return(MAXBASE);
326 	else if (isupper(c))
327 		return(c-'A'+10);
328 	else
329 		return(c-'a'+10);
330 }
331 
332 symchar(int dig)
333 {
334 	if (lastc=='\\') {
335 		readchar();
336 		return(TRUE);
337 	}
338 	return(isalpha(lastc) || lastc=='_' || dig && isdigit(lastc));
339 }
340 
341 varchk(int name)
342 {
343 	if (isdigit(name))
344 		return(name-'0');
345 	if (isalpha(name))
346 		return((name&037)-1+10);
347 	return(-1);
348 }
349 
350 static long
351 round(long a, long b)
352 {
353 	long w;
354 
355 	w = (a/b)*b;
356 	if (a!=w)
357 		w += b;
358 	return(w);
359 }
360