xref: /f-stack/freebsd/ddb/db_expr.c (revision 22ce4aff)
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