1/* $NetBSD: db_expr.c,v 1.16 2009/03/07 22:02:17 ad Exp $ */
2
3/*
4 * Mach Operating System
5 * Copyright (c) 1991,1990 Carnegie Mellon University
6 * All Rights Reserved.
7 *
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie the
26 * rights to redistribute these changes.
27 *
28 * Author: David B. Golub, Carnegie Mellon University
29 * Date: 7/90
30 */
31
32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: db_expr.c,v 1.16 2009/03/07 22:02:17 ad Exp $");
34
35#include <sys/param.h>
36#include <sys/proc.h>
37
38#include <ddb/ddb.h>
39
40static bool db_term(db_expr_t *);
41static bool db_unary(db_expr_t *);
42static bool db_mult_expr(db_expr_t *);
43static bool db_add_expr(db_expr_t *);
44static bool db_shift_expr(db_expr_t *);
45
46static bool
47db_term(db_expr_t *valuep)
48{
49 int t;
50
51 t = db_read_token();
52 if (t == tIDENT) {
53 if (!db_value_of_name(db_tok_string, valuep)) {
54 db_expr_t v = 0;
55 int i, c, byte;
56
57 /* See if we can make a number out of all of it */
58 for (i = 0; (c = db_tok_string[i]) != '\0'; i++) {
59 byte = 0;
60 if (c >= '0' && c <= '9')
61 byte = c - '0';
62 else if (db_radix == 16 && c >= 'a' && c <= 'f')
63 byte = c - 'a' + 10;
64 else if (db_radix == 16 && c >= 'A' && c <= 'F')
65 byte = c - 'A' + 10;
66 else
67 db_error("Symbol not found\n");
68 /*NOTREACHED*/
69 v = v * db_radix + byte;
70 }
71 *valuep = (db_expr_t)v;
72 }
73 return (true);
74 }
75 if (t == tNUMBER) {
76 *valuep = (db_expr_t)db_tok_number;
77 return (true);
78 }
79 if (t == tDOT) {
80 *valuep = (db_expr_t)db_dot;
81 return (true);
82 }
83 if (t == tDOTDOT) {
84 *valuep = (db_expr_t)db_prev;
85 return (true);
86 }
87 if (t == tPLUS) {
88 *valuep = (db_expr_t) db_next;
89 return (true);
90 }
91 if (t == tDITTO) {
92 *valuep = (db_expr_t)db_last_addr;
93 return (true);
94 }
95 if (t == tDOLLAR) {
96 if (!db_get_variable(valuep))
97 return (false);
98 return (true);
99 }
100 if (t == tLPAREN) {
101 if (!db_expression(valuep)) {
102 db_error("Syntax error\n");
103 /*NOTREACHED*/
104 }
105 t = db_read_token();
106 if (t != tRPAREN) {
107 db_error("Syntax error\n");
108 /*NOTREACHED*/
109 }
110 return (true);
111 }
112 db_unread_token(t);
113 return (false);
114}
115
116static bool
117db_unary(db_expr_t *valuep)
118{
119 int t;
120
121 t = db_read_token();
122 if (t == tMINUS) {
123 if (!db_unary(valuep)) {
124 db_error("Syntax error\n");
125 /*NOTREACHED*/
126 }
127 *valuep = -*valuep;
128 return (true);
129 }
130 if (t == tSTAR) {
131 /* indirection */
132 if (!db_unary(valuep)) {
133 db_error("Syntax error\n");
134 /*NOTREACHED*/
135 }
136 *valuep = db_get_value((db_addr_t)*valuep, sizeof(db_expr_t),
137 false);
138 return (true);
139 }
140 db_unread_token(t);
141 return (db_term(valuep));
142}
143
144static bool
145db_mult_expr(db_expr_t *valuep)
146{
147 db_expr_t lhs, rhs;
148 int t;
149
150 if (!db_unary(&lhs))
151 return (false);
152
153 t = db_read_token();
154 while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH) {
155 if (!db_term(&rhs)) {
156 db_error("Syntax error\n");
157 /*NOTREACHED*/
158 }
159 if (t == tSTAR)
160 lhs *= rhs;
161 else {
162 if (rhs == 0) {
163 db_error("Divide by 0\n");
164 /*NOTREACHED*/
165 }
166 if (t == tSLASH)
167 lhs /= rhs;
168 else if (t == tPCT)
169 lhs %= rhs;
170 else
171 lhs = ((lhs+rhs-1)/rhs)*rhs;
172 }
173 t = db_read_token();
174 }
175 db_unread_token(t);
176 *valuep = lhs;
177 return (true);
178}
179
180static bool
181db_add_expr(db_expr_t *valuep)
182{
183 db_expr_t lhs, rhs;
184 int t;
185
186 if (!db_mult_expr(&lhs))
187 return (false);
188
189 t = db_read_token();
190 while (t == tPLUS || t == tMINUS) {
191 if (!db_mult_expr(&rhs)) {
192 db_error("Syntax error\n");
193 /*NOTREACHED*/
194 }
195 if (t == tPLUS)
196 lhs += rhs;
197 else
198 lhs -= rhs;
199 t = db_read_token();
200 }
201 db_unread_token(t);
202 *valuep = lhs;
203 return (true);
204}
205
206static bool
207db_shift_expr(db_expr_t *valuep)
208{
209 db_expr_t lhs, rhs;
210 int t;
211
212 if (!db_add_expr(&lhs))
213 return (false);
214
215 t = db_read_token();
216 while (t == tSHIFT_L || t == tSHIFT_R) {
217 if (!db_add_expr(&rhs)) {
218 db_error("Syntax error\n");
219 /*NOTREACHED*/
220 }
221 if (rhs < 0) {
222 db_error("Negative shift amount\n");
223 /*NOTREACHED*/
224 }
225 if (t == tSHIFT_L)
226 lhs <<= rhs;
227 else {
228 /* Shift right is unsigned */
229 lhs = (unsigned long) lhs >> rhs;
230 }
231 t = db_read_token();
232 }
233 db_unread_token(t);
234 *valuep = lhs;
235 return (true);
236}
237
238int
239db_expression(db_expr_t *valuep)
240{
241
242 return (db_shift_expr(valuep));
243}
244