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/param.h>
34 #include <sys/systm.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
db_term(db_expr_t * valuep)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_printf("Symbol '%s' not found\n", db_tok_string);
61 db_error(NULL);
62 /*NOTREACHED*/
63 }
64 return (true);
65 }
66 if (t == tNUMBER) {
67 *valuep = (db_expr_t)db_tok_number;
68 return (true);
69 }
70 if (t == tDOT) {
71 *valuep = (db_expr_t)db_dot;
72 return (true);
73 }
74 if (t == tDOTDOT) {
75 *valuep = (db_expr_t)db_prev;
76 return (true);
77 }
78 if (t == tPLUS) {
79 *valuep = (db_expr_t) db_next;
80 return (true);
81 }
82 if (t == tDITTO) {
83 *valuep = (db_expr_t)db_last_addr;
84 return (true);
85 }
86 if (t == tDOLLAR) {
87 if (!db_get_variable(valuep))
88 return (false);
89 return (true);
90 }
91 if (t == tLPAREN) {
92 if (!db_expression(valuep)) {
93 db_printf("Expression syntax error after '%c'\n", '(');
94 db_error(NULL);
95 /*NOTREACHED*/
96 }
97 t = db_read_token();
98 if (t != tRPAREN) {
99 db_printf("Expression syntax error -- expected '%c'\n", ')');
100 db_error(NULL);
101 /*NOTREACHED*/
102 }
103 return (true);
104 }
105 db_unread_token(t);
106 return (false);
107 }
108
109 static bool
db_unary(db_expr_t * valuep)110 db_unary(db_expr_t *valuep)
111 {
112 int t;
113
114 t = db_read_token();
115 if (t == tMINUS) {
116 if (!db_unary(valuep)) {
117 db_printf("Expression syntax error after '%c'\n", '-');
118 db_error(NULL);
119 /*NOTREACHED*/
120 }
121 *valuep = -*valuep;
122 return (true);
123 }
124 if (t == tEXCL) {
125 if (!db_unary(valuep)) {
126 db_printf("Expression syntax error after '%c'\n", '!');
127 db_error(NULL);
128 /* NOTREACHED */
129 }
130 *valuep = (!(*valuep));
131 return (true);
132 }
133 if (t == tBIT_NOT) {
134 if (!db_unary(valuep)) {
135 db_printf("Expression syntax error after '%c'\n", '~');
136 db_error(NULL);
137 /* NOTREACHED */
138 }
139 *valuep = (~(*valuep));
140 return (true);
141 }
142 if (t == tSTAR) {
143 /* indirection */
144 if (!db_unary(valuep)) {
145 db_printf("Expression syntax error after '%c'\n", '*');
146 db_error(NULL);
147 /*NOTREACHED*/
148 }
149 *valuep = db_get_value((db_addr_t)*valuep, sizeof(void *),
150 false);
151 return (true);
152 }
153 db_unread_token(t);
154 return (db_term(valuep));
155 }
156
157 static bool
db_mult_expr(db_expr_t * valuep)158 db_mult_expr(db_expr_t *valuep)
159 {
160 db_expr_t lhs, rhs;
161 int t;
162
163 if (!db_unary(&lhs))
164 return (false);
165
166 t = db_read_token();
167 while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH ||
168 t == tBIT_AND ) {
169 if (!db_term(&rhs)) {
170 db_printf("Expression syntax error after '%c'\n",
171 t == tSTAR ? '*' : t == tSLASH ? '/' : t == tPCT ? '%' :
172 t == tHASH ? '#' : '&');
173 db_error(NULL);
174 /*NOTREACHED*/
175 }
176 switch(t) {
177 case tSTAR:
178 lhs *= rhs;
179 break;
180 case tBIT_AND:
181 lhs &= rhs;
182 break;
183 default:
184 if (rhs == 0) {
185 db_error("Division by 0\n");
186 /*NOTREACHED*/
187 }
188 if (t == tSLASH)
189 lhs /= rhs;
190 else if (t == tPCT)
191 lhs %= rhs;
192 else
193 lhs = roundup(lhs, rhs);
194 }
195 t = db_read_token();
196 }
197 db_unread_token(t);
198 *valuep = lhs;
199 return (true);
200 }
201
202 static bool
db_add_expr(db_expr_t * valuep)203 db_add_expr(db_expr_t *valuep)
204 {
205 db_expr_t lhs, rhs;
206 int t;
207
208 if (!db_mult_expr(&lhs))
209 return (false);
210
211 t = db_read_token();
212 while (t == tPLUS || t == tMINUS || t == tBIT_OR) {
213 if (!db_mult_expr(&rhs)) {
214 db_printf("Expression syntax error after '%c'\n",
215 t == tPLUS ? '+' : t == tMINUS ? '-' : '|');
216 db_error(NULL);
217 /*NOTREACHED*/
218 }
219 switch (t) {
220 case tPLUS:
221 lhs += rhs;
222 break;
223 case tMINUS:
224 lhs -= rhs;
225 break;
226 case tBIT_OR:
227 lhs |= rhs;
228 break;
229 default:
230 __assert_unreachable();
231 }
232 t = db_read_token();
233 }
234 db_unread_token(t);
235 *valuep = lhs;
236 return (true);
237 }
238
239 static bool
db_shift_expr(db_expr_t * valuep)240 db_shift_expr(db_expr_t *valuep)
241 {
242 db_expr_t lhs, rhs;
243 int t;
244
245 if (!db_add_expr(&lhs))
246 return (false);
247 t = db_read_token();
248 while (t == tSHIFT_L || t == tSHIFT_R) {
249 if (!db_add_expr(&rhs)) {
250 db_printf("Expression syntax error after '%s'\n",
251 t == tSHIFT_L ? "<<" : ">>");
252 db_error(NULL);
253 /*NOTREACHED*/
254 }
255 if (rhs < 0) {
256 db_printf("Negative shift amount %jd\n", (intmax_t)rhs);
257 db_error(NULL);
258 /*NOTREACHED*/
259 }
260 if (t == tSHIFT_L)
261 lhs <<= rhs;
262 else {
263 /* Shift right is unsigned */
264 lhs = (db_addr_t)lhs >> rhs;
265 }
266 t = db_read_token();
267 }
268 db_unread_token(t);
269 *valuep = lhs;
270 return (true);
271 }
272
273 static bool
db_logical_relation_expr(db_expr_t * valuep)274 db_logical_relation_expr(
275 db_expr_t *valuep)
276 {
277 db_expr_t lhs, rhs;
278 int t;
279
280 if (!db_shift_expr(&lhs))
281 return (false);
282
283 t = db_read_token();
284 while (t == tLOG_EQ || t == tLOG_NOT_EQ || t == tGREATER ||
285 t == tGREATER_EQ || t == tLESS || t == tLESS_EQ) {
286 if (!db_shift_expr(&rhs)) {
287 db_printf("Expression syntax error after '%s'\n",
288 t == tLOG_EQ ? "==" : t == tLOG_NOT_EQ ? "!=" :
289 t == tGREATER ? ">" : t == tGREATER_EQ ? ">=" :
290 t == tLESS ? "<" : "<=");
291 db_error(NULL);
292 /*NOTREACHED*/
293 }
294 switch(t) {
295 case tLOG_EQ:
296 lhs = (lhs == rhs);
297 break;
298 case tLOG_NOT_EQ:
299 lhs = (lhs != rhs);
300 break;
301 case tGREATER:
302 lhs = (lhs > rhs);
303 break;
304 case tGREATER_EQ:
305 lhs = (lhs >= rhs);
306 break;
307 case tLESS:
308 lhs = (lhs < rhs);
309 break;
310 case tLESS_EQ:
311 lhs = (lhs <= rhs);
312 break;
313 default:
314 __assert_unreachable();
315 }
316 t = db_read_token();
317 }
318 db_unread_token(t);
319 *valuep = lhs;
320 return (true);
321 }
322
323 static bool
db_logical_and_expr(db_expr_t * valuep)324 db_logical_and_expr(
325 db_expr_t *valuep)
326 {
327 db_expr_t lhs, rhs;
328 int t;
329
330 if (!db_logical_relation_expr(&lhs))
331 return (false);
332
333 t = db_read_token();
334 while (t == tLOG_AND) {
335 if (!db_logical_relation_expr(&rhs)) {
336 db_printf("Expression syntax error after '%s'\n", "&&");
337 db_error(NULL);
338 /*NOTREACHED*/
339 }
340 lhs = (lhs && rhs);
341 t = db_read_token();
342 }
343 db_unread_token(t);
344 *valuep = lhs;
345 return (true);
346 }
347
348 static bool
db_logical_or_expr(db_expr_t * valuep)349 db_logical_or_expr(
350 db_expr_t *valuep)
351 {
352 db_expr_t lhs, rhs;
353 int t;
354
355 if (!db_logical_and_expr(&lhs))
356 return(false);
357
358 t = db_read_token();
359 while (t == tLOG_OR) {
360 if (!db_logical_and_expr(&rhs)) {
361 db_printf("Expression syntax error after '%s'\n", "||");
362 db_error(NULL);
363 /*NOTREACHED*/
364 }
365 lhs = (lhs || rhs);
366 t = db_read_token();
367 }
368 db_unread_token(t);
369 *valuep = lhs;
370 return (true);
371 }
372
373 int
db_expression(db_expr_t * valuep)374 db_expression(db_expr_t *valuep)
375 {
376 return (db_logical_or_expr(valuep));
377 }
378