xref: /freebsd/sys/ddb/db_expr.c (revision 243e928310d073338c5ec089f0dce238a80b9866)
1 /*-
2  * Mach Operating System
3  * Copyright (c) 1991,1990 Carnegie Mellon University
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify and distribute this software and its
7  * documentation is hereby granted, provided that both the copyright
8  * notice and this permission notice appear in all copies of the
9  * software, derivative works or modified versions, and any portions
10  * thereof, and that both notices appear in supporting documentation.
11  *
12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15  *
16  * Carnegie Mellon requests users of this software to return to
17  *
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19  *  School of Computer Science
20  *  Carnegie Mellon University
21  *  Pittsburgh PA 15213-3890
22  *
23  * any improvements or extensions that they make and grant Carnegie the
24  * rights to redistribute these changes.
25  */
26 /*
27  *	Author: David B. Golub, Carnegie Mellon University
28  *	Date:	7/90
29  */
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #include <sys/param.h>
35 
36 #include <ddb/ddb.h>
37 #include <ddb/db_lex.h>
38 #include <ddb/db_access.h>
39 #include <ddb/db_command.h>
40 
41 static bool	db_add_expr(db_expr_t *valuep);
42 static bool	db_mult_expr(db_expr_t *valuep);
43 static bool	db_shift_expr(db_expr_t *valuep);
44 static bool	db_term(db_expr_t *valuep);
45 static bool	db_unary(db_expr_t *valuep);
46 static bool	db_logical_or_expr(db_expr_t *valuep);
47 static bool	db_logical_and_expr(db_expr_t *valuep);
48 static bool	db_logical_relation_expr(db_expr_t *valuep);
49 
50 static bool
51 db_term(db_expr_t *valuep)
52 {
53 	int	t;
54 
55 	t = db_read_token();
56 	if (t == tIDENT) {
57 	    if (!db_value_of_name(db_tok_string, valuep) &&
58 		!db_value_of_name_pcpu(db_tok_string, valuep) &&
59 		!db_value_of_name_vnet(db_tok_string, valuep)) {
60 		db_error("Symbol not found\n");
61 		/*NOTREACHED*/
62 	    }
63 	    return (true);
64 	}
65 	if (t == tNUMBER) {
66 	    *valuep = (db_expr_t)db_tok_number;
67 	    return (true);
68 	}
69 	if (t == tDOT) {
70 	    *valuep = (db_expr_t)db_dot;
71 	    return (true);
72 	}
73 	if (t == tDOTDOT) {
74 	    *valuep = (db_expr_t)db_prev;
75 	    return (true);
76 	}
77 	if (t == tPLUS) {
78 	    *valuep = (db_expr_t) db_next;
79 	    return (true);
80 	}
81 	if (t == tDITTO) {
82 	    *valuep = (db_expr_t)db_last_addr;
83 	    return (true);
84 	}
85 	if (t == tDOLLAR) {
86 	    if (!db_get_variable(valuep))
87 		return (false);
88 	    return (true);
89 	}
90 	if (t == tLPAREN) {
91 	    if (!db_expression(valuep)) {
92 		db_error("Syntax error\n");
93 		/*NOTREACHED*/
94 	    }
95 	    t = db_read_token();
96 	    if (t != tRPAREN) {
97 		db_error("Syntax error\n");
98 		/*NOTREACHED*/
99 	    }
100 	    return (true);
101 	}
102 	db_unread_token(t);
103 	return (false);
104 }
105 
106 static bool
107 db_unary(db_expr_t *valuep)
108 {
109 	int	t;
110 
111 	t = db_read_token();
112 	if (t == tMINUS) {
113 	    if (!db_unary(valuep)) {
114 		db_printf("Expression syntax error after '%c'\n", '-');
115 		db_error(NULL);
116 		/*NOTREACHED*/
117 	    }
118 	    *valuep = -*valuep;
119 	    return (true);
120 	}
121 	if (t == tEXCL) {
122 	    if(!db_unary(valuep)) {
123 		db_printf("Expression syntax error after '%c'\n", '!');
124 		db_error(NULL);
125 		/* NOTREACHED  */
126 	    }
127 	    *valuep = (!(*valuep));
128 	    return (true);
129 	}
130 	if (t == tBIT_NOT) {
131 	    if(!db_unary(valuep)) {
132 		db_printf("Expression syntax error after '%c'\n", '~');
133 		db_error(NULL);
134 		/* NOTREACHED */
135 	    }
136 	    *valuep = (~(*valuep));
137 	    return (true);
138 	}
139 	if (t == tSTAR) {
140 	    /* indirection */
141 	    if (!db_unary(valuep)) {
142 		db_printf("Expression syntax error after '%c'\n", '*');
143 		db_error(NULL);
144 		/*NOTREACHED*/
145 	    }
146 	    *valuep = db_get_value((db_addr_t)*valuep, sizeof(void *),
147 		false);
148 	    return (true);
149 	}
150 	db_unread_token(t);
151 	return (db_term(valuep));
152 }
153 
154 static bool
155 db_mult_expr(db_expr_t *valuep)
156 {
157 	db_expr_t	lhs, rhs;
158 	int		t;
159 
160 	if (!db_unary(&lhs))
161 	    return (false);
162 
163 	t = db_read_token();
164 	while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH ||
165 	    t == tBIT_AND ) {
166 	    if (!db_term(&rhs)) {
167 		db_printf("Expression syntax error after '%c'\n", '!');
168 		db_error(NULL);
169 		/*NOTREACHED*/
170 	    }
171 	    switch(t)  {
172 		case tSTAR:
173 		    lhs *= rhs;
174 		    break;
175 		case tBIT_AND:
176 		    lhs &= rhs;
177 		    break;
178 		default:
179 		    if (rhs == 0) {
180 			db_error("Divide by 0\n");
181 			/*NOTREACHED*/
182 		    }
183 		    if (t == tSLASH)
184 			lhs /= rhs;
185 		    else if (t == tPCT)
186 			lhs %= rhs;
187 		    else
188 			lhs = roundup(lhs, rhs);
189 	    }
190 	    t = db_read_token();
191 	}
192 	db_unread_token(t);
193 	*valuep = lhs;
194 	return (true);
195 }
196 
197 static bool
198 db_add_expr(db_expr_t *valuep)
199 {
200 	db_expr_t	lhs, rhs;
201 	int		t;
202 	char		c;
203 
204 	if (!db_mult_expr(&lhs))
205 	    return (false);
206 
207 	t = db_read_token();
208 	while (t == tPLUS || t == tMINUS || t == tBIT_OR) {
209 	    if (!db_mult_expr(&rhs)) {
210 		c = db_tok_string[0];
211 		db_printf("Expression syntax error after '%c'\n", c);
212 		db_error(NULL);
213 		/*NOTREACHED*/
214 	    }
215 	    switch (t) {
216 	    case tPLUS:
217 		lhs += rhs;
218 		break;
219 	    case tMINUS:
220 		lhs -= rhs;
221 		break;
222 	    case tBIT_OR:
223 		lhs |= rhs;
224 		break;
225 	    default:
226 		__unreachable();
227 	    }
228 	    t = db_read_token();
229 	}
230 	db_unread_token(t);
231 	*valuep = lhs;
232 	return (true);
233 }
234 
235 static bool
236 db_shift_expr(db_expr_t *valuep)
237 {
238 	db_expr_t	lhs, rhs;
239 	int		t;
240 
241 	if (!db_add_expr(&lhs))
242 		return (false);
243 	t = db_read_token();
244 	while (t == tSHIFT_L || t == tSHIFT_R) {
245 	    if (!db_add_expr(&rhs)) {
246 		db_error("Syntax error\n");
247 		/*NOTREACHED*/
248 	    }
249 	    if (rhs < 0) {
250 		db_error("Negative shift amount\n");
251 		/*NOTREACHED*/
252 	    }
253 	    if (t == tSHIFT_L)
254 		lhs <<= rhs;
255 	    else {
256 		/* Shift right is unsigned */
257 		lhs = (unsigned) lhs >> rhs;
258 	    }
259 	    t = db_read_token();
260 	}
261 	db_unread_token(t);
262 	*valuep = lhs;
263 	return (true);
264 }
265 
266 static bool
267 db_logical_relation_expr(
268 	db_expr_t *valuep)
269 {
270 	db_expr_t	lhs, rhs;
271 	int		t;
272 	char		op[3];
273 
274 	if (!db_shift_expr(&lhs))
275 	    return (false);
276 
277 	t = db_read_token();
278 	while (t == tLOG_EQ || t == tLOG_NOT_EQ || t == tGREATER ||
279 	    t == tGREATER_EQ || t == tLESS || t == tLESS_EQ) {
280 	    op[0] = db_tok_string[0];
281 	    op[1] = db_tok_string[1];
282 	    op[2] = 0;
283 	    if (!db_shift_expr(&rhs)) {
284 		db_printf("Expression syntax error after \"%s\"\n", op);
285 		db_error(NULL);
286 		/*NOTREACHED*/
287 	    }
288 	    switch(t) {
289 		case tLOG_EQ:
290 		    lhs = (lhs == rhs);
291 		    break;
292 		case tLOG_NOT_EQ:
293 		    lhs = (lhs != rhs);
294 		    break;
295 		case tGREATER:
296 		    lhs = (lhs > rhs);
297 		    break;
298 		case tGREATER_EQ:
299 		    lhs = (lhs >= rhs);
300 		    break;
301 		case tLESS:
302 		    lhs = (lhs < rhs);
303 		    break;
304 		case tLESS_EQ:
305 		    lhs = (lhs <= rhs);
306 		    break;
307 		default:
308 		    __unreachable();
309 	    }
310 	    t = db_read_token();
311 	}
312 	db_unread_token(t);
313 	*valuep = lhs;
314 	return (true);
315 }
316 
317 static bool
318 db_logical_and_expr(
319 	db_expr_t *valuep)
320 {
321 	db_expr_t	lhs, rhs;
322 	int		t;
323 
324 	if (!db_logical_relation_expr(&lhs))
325 	    return (false);
326 
327 	t = db_read_token();
328 	while (t == tLOG_AND) {
329 	    if (!db_logical_relation_expr(&rhs)) {
330 		db_printf("Expression syntax error after '%s'\n", "&&");
331 		db_error(NULL);
332 		/*NOTREACHED*/
333 	    }
334 	    lhs = (lhs && rhs);
335 	    t = db_read_token();
336 	}
337 	db_unread_token(t);
338 	*valuep = lhs;
339 	return (true);
340 }
341 
342 static bool
343 db_logical_or_expr(
344 	db_expr_t *valuep)
345 {
346 	db_expr_t	lhs, rhs;
347 	int		t;
348 
349 	if (!db_logical_and_expr(&lhs))
350 		return(false);
351 
352 	t = db_read_token();
353 	while (t == tLOG_OR) {
354 		if (!db_logical_and_expr(&rhs)) {
355 			db_printf("Expression syntax error after '%s'\n", "||");
356 			db_error(NULL);
357 			/*NOTREACHED*/
358 		}
359 		lhs = (lhs || rhs);
360 		t = db_read_token();
361 	}
362 	db_unread_token(t);
363 	*valuep = lhs;
364 	return (true);
365 }
366 
367 int
368 db_expression(db_expr_t *valuep)
369 {
370 	return (db_logical_or_expr(valuep));
371 }
372