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