db_expr.c revision 308418
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: stable/11/sys/ddb/db_expr.c 308418 2016-11-07 12:10:17Z kib $");
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
41static bool	db_add_expr(db_expr_t *valuep);
42static bool	db_mult_expr(db_expr_t *valuep);
43static bool	db_shift_expr(db_expr_t *valuep);
44static bool	db_term(db_expr_t *valuep);
45static bool	db_unary(db_expr_t *valuep);
46static bool	db_logical_or_expr(db_expr_t *valuep);
47static bool	db_logical_and_expr(db_expr_t *valuep);
48static bool	db_logical_relation_expr(db_expr_t *valuep);
49
50static bool
51db_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
109static bool
110db_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
157static bool
158db_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
202static bool
203db_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		__unreachable();
231	    }
232	    t = db_read_token();
233	}
234	db_unread_token(t);
235	*valuep = lhs;
236	return (true);
237}
238
239static bool
240db_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 = (unsigned) lhs >> rhs;
265	    }
266	    t = db_read_token();
267	}
268	db_unread_token(t);
269	*valuep = lhs;
270	return (true);
271}
272
273static bool
274db_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		    __unreachable();
315	    }
316	    t = db_read_token();
317	}
318	db_unread_token(t);
319	*valuep = lhs;
320	return (true);
321}
322
323static bool
324db_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
348static bool
349db_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
373int
374db_expression(db_expr_t *valuep)
375{
376	return (db_logical_or_expr(valuep));
377}
378