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