xref: /freebsd/sys/ddb/db_expr.c (revision 45dc13f1ea17f98ac7b92768814d579ac48bfd04)
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$");
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 
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 
47 static bool
48 db_term(db_expr_t *valuep)
49 {
50 	int	t;
51 
52 	t = db_read_token();
53 	if (t == tIDENT) {
54 	    if (!db_value_of_name(db_tok_string, valuep) &&
55 		!db_value_of_name_pcpu(db_tok_string, valuep) &&
56 		!db_value_of_name_vnet(db_tok_string, valuep)) {
57 		db_error("Symbol not found\n");
58 		/*NOTREACHED*/
59 	    }
60 	    return (true);
61 	}
62 	if (t == tNUMBER) {
63 	    *valuep = (db_expr_t)db_tok_number;
64 	    return (true);
65 	}
66 	if (t == tDOT) {
67 	    *valuep = (db_expr_t)db_dot;
68 	    return (true);
69 	}
70 	if (t == tDOTDOT) {
71 	    *valuep = (db_expr_t)db_prev;
72 	    return (true);
73 	}
74 	if (t == tPLUS) {
75 	    *valuep = (db_expr_t) db_next;
76 	    return (true);
77 	}
78 	if (t == tDITTO) {
79 	    *valuep = (db_expr_t)db_last_addr;
80 	    return (true);
81 	}
82 	if (t == tDOLLAR) {
83 	    if (!db_get_variable(valuep))
84 		return (false);
85 	    return (true);
86 	}
87 	if (t == tLPAREN) {
88 	    if (!db_expression(valuep)) {
89 		db_error("Syntax error\n");
90 		/*NOTREACHED*/
91 	    }
92 	    t = db_read_token();
93 	    if (t != tRPAREN) {
94 		db_error("Syntax error\n");
95 		/*NOTREACHED*/
96 	    }
97 	    return (true);
98 	}
99 	db_unread_token(t);
100 	return (false);
101 }
102 
103 static bool
104 db_unary(db_expr_t *valuep)
105 {
106 	int	t;
107 
108 	t = db_read_token();
109 	if (t == tMINUS) {
110 	    if (!db_unary(valuep)) {
111 		db_error("Syntax error\n");
112 		/*NOTREACHED*/
113 	    }
114 	    *valuep = -*valuep;
115 	    return (true);
116 	}
117 	if (t == tSTAR) {
118 	    /* indirection */
119 	    if (!db_unary(valuep)) {
120 		db_error("Syntax error\n");
121 		/*NOTREACHED*/
122 	    }
123 	    *valuep = db_get_value((db_addr_t)*valuep, sizeof(void *), false);
124 	    return (true);
125 	}
126 	db_unread_token(t);
127 	return (db_term(valuep));
128 }
129 
130 static bool
131 db_mult_expr(db_expr_t *valuep)
132 {
133 	db_expr_t	lhs, rhs;
134 	int		t;
135 
136 	if (!db_unary(&lhs))
137 	    return (false);
138 
139 	t = db_read_token();
140 	while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH) {
141 	    if (!db_term(&rhs)) {
142 		db_error("Syntax error\n");
143 		/*NOTREACHED*/
144 	    }
145 	    if (t == tSTAR)
146 		lhs *= rhs;
147 	    else {
148 		if (rhs == 0) {
149 		    db_error("Divide by 0\n");
150 		    /*NOTREACHED*/
151 		}
152 		if (t == tSLASH)
153 		    lhs /= rhs;
154 		else if (t == tPCT)
155 		    lhs %= rhs;
156 		else
157 		    lhs = ((lhs+rhs-1)/rhs)*rhs;
158 	    }
159 	    t = db_read_token();
160 	}
161 	db_unread_token(t);
162 	*valuep = lhs;
163 	return (true);
164 }
165 
166 static bool
167 db_add_expr(db_expr_t *valuep)
168 {
169 	db_expr_t	lhs, rhs;
170 	int		t;
171 
172 	if (!db_mult_expr(&lhs))
173 	    return (false);
174 
175 	t = db_read_token();
176 	while (t == tPLUS || t == tMINUS) {
177 	    if (!db_mult_expr(&rhs)) {
178 		db_error("Syntax error\n");
179 		/*NOTREACHED*/
180 	    }
181 	    if (t == tPLUS)
182 		lhs += rhs;
183 	    else
184 		lhs -= rhs;
185 	    t = db_read_token();
186 	}
187 	db_unread_token(t);
188 	*valuep = lhs;
189 	return (true);
190 }
191 
192 static bool
193 db_shift_expr(db_expr_t *valuep)
194 {
195 	db_expr_t	lhs, rhs;
196 	int		t;
197 
198 	if (!db_add_expr(&lhs))
199 	    return (false);
200 
201 	t = db_read_token();
202 	while (t == tSHIFT_L || t == tSHIFT_R) {
203 	    if (!db_add_expr(&rhs)) {
204 		db_error("Syntax error\n");
205 		/*NOTREACHED*/
206 	    }
207 	    if (rhs < 0) {
208 		db_error("Negative shift amount\n");
209 		/*NOTREACHED*/
210 	    }
211 	    if (t == tSHIFT_L)
212 		lhs <<= rhs;
213 	    else {
214 		/* Shift right is unsigned */
215 		lhs = (unsigned) lhs >> rhs;
216 	    }
217 	    t = db_read_token();
218 	}
219 	db_unread_token(t);
220 	*valuep = lhs;
221 	return (true);
222 }
223 
224 int
225 db_expression(db_expr_t *valuep)
226 {
227 	return (db_shift_expr(valuep));
228 }
229