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