]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_expr.c
a7987dc5768d59a73dd8559ee181cbf084fed28f
[apple/xnu.git] / osfmk / ddb / db_expr.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 * @OSF_COPYRIGHT@
25 */
26 /*
27 * Mach Operating System
28 * Copyright (c) 1991,1990 Carnegie Mellon University
29 * All Rights Reserved.
30 *
31 * Permission to use, copy, modify and distribute this software and its
32 * documentation is hereby granted, provided that both the copyright
33 * notice and this permission notice appear in all copies of the
34 * software, derivative works or modified versions, and any portions
35 * thereof, and that both notices appear in supporting documentation.
36 *
37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 *
41 * Carnegie Mellon requests users of this software to return to
42 *
43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
44 * School of Computer Science
45 * Carnegie Mellon University
46 * Pittsburgh PA 15213-3890
47 *
48 * any improvements or extensions that they make and grant Carnegie Mellon
49 * the rights to redistribute these changes.
50 */
51 /*
52 */
53 /*
54 * Author: David B. Golub, Carnegie Mellon University
55 * Date: 7/90
56 */
57
58 #include <mach/boolean.h>
59 #include <machine/db_machdep.h>
60 #include <ddb/db_access.h>
61 #include <ddb/db_command.h>
62 #include <ddb/db_expr.h>
63 #include <ddb/db_lex.h>
64 #include <ddb/db_output.h> /* For db_printf() */
65 #include <ddb/db_sym.h>
66 #include <ddb/db_variables.h>
67 #include <kern/task.h>
68
69
70
71 /* Prototypes for functions local to this file. XXX -- should be static!
72 */
73 boolean_t db_term(db_expr_t *valuep);
74 boolean_t db_unary(db_expr_t *valuep);
75 boolean_t db_mult_expr(db_expr_t *valuep);
76 boolean_t db_add_expr(db_expr_t *valuep);
77 boolean_t db_shift_expr(db_expr_t *valuep);
78 boolean_t db_logical_relation_expr(db_expr_t *valuep);
79 boolean_t db_logical_and_expr(db_expr_t *valuep);
80 boolean_t db_logical_or_expr(db_expr_t *valuep);
81
82
83 /* try to interpret unknown symbols as hexadecimal constants */
84 int db_allow_unprefixed_hexa = 1;
85
86 boolean_t
87 db_term(db_expr_t *valuep)
88 {
89 int t;
90 boolean_t valid_symbol = FALSE;
91 boolean_t valid_hexa = FALSE;
92
93 switch(t = db_read_token()) {
94 case tIDENT:
95 if (db_value_of_name(db_tok_string, valuep)) {
96 valid_symbol = TRUE;
97 }
98 if (db_allow_unprefixed_hexa && db_radix == 16 &&
99 db_tok_string) {
100 char *cp;
101 db_expr_t value;
102
103 value = 0;
104 valid_hexa = TRUE;
105 for (cp = db_tok_string; *cp; cp++) {
106 if (*cp >= 'a' && *cp <= 'f') {
107 value = value * 16 + 10 + (*cp - 'a');
108 } else if (*cp >= 'A' && *cp <= 'F') {
109 value = value * 16 + 10 + (*cp - 'A');
110 } else if (*cp >= '0' && *cp <= '9') {
111 value = value * 16 + (*cp - '0');
112 } else {
113 valid_hexa = FALSE;
114 break;
115 }
116 }
117 if (valid_hexa) {
118 if (valid_symbol) {
119 db_printf("Ambiguous constant %x used as a symbol\n",
120 value);
121 } else {
122 *valuep = value;
123 }
124 }
125 }
126 if (!valid_symbol && !valid_hexa) {
127 db_printf("Symbol \"%s\" not found\n", db_tok_string);
128 db_error(0);
129 /*NOTREACHED*/
130 }
131 return (TRUE);
132 case tNUMBER:
133 *valuep = /*(db_expr_t)*/db_tok_number;
134 return (TRUE);
135 case tDOT:
136 *valuep = (db_expr_t)db_dot;
137 return (TRUE);
138 case tDOTDOT:
139 *valuep = (db_expr_t)db_prev;
140 return (TRUE);
141 case tPLUS:
142 *valuep = (db_expr_t) db_next;
143 return (TRUE);
144 case tQUOTE:
145 *valuep = (db_expr_t)db_last_addr;
146 return (TRUE);
147 case tDOLLAR:
148 if (!db_get_variable(valuep))
149 return (FALSE);
150 return (TRUE);
151 case tLPAREN:
152 if (!db_expression(valuep)) {
153 db_error("Unmached ()s\n");
154 /*NOTREACHED*/
155 }
156 t = db_read_token();
157 if (t != tRPAREN) {
158 db_printf("')' expected at \"%s...\"\n", db_tok_string);
159 db_error(0);
160 /*NOTREACHED*/
161 }
162 return (TRUE);
163 case tSTRING:
164 {
165 static db_tok_offset = 0;
166 char *sp, *cp;
167
168 sp = (char *)db_tok_string + db_tok_offset;
169 *valuep = *(int *)sp;
170 for (cp = sp;
171 *cp && cp < sp + sizeof (int);
172 cp++);
173 if (cp == sp + sizeof (int) && *cp) {
174 db_tok_offset += sizeof (int);
175 db_unread_token(t);
176 } else {
177 db_tok_offset = 0;
178 }
179 return (TRUE);
180 }
181 default:
182 db_unread_token(t);
183 return (FALSE);
184 }
185 }
186
187 int
188 db_size_option(
189 char *modif,
190 boolean_t *u_option,
191 boolean_t *t_option)
192 {
193 register char *p;
194 int size = sizeof(int);
195
196 *u_option = FALSE;
197 *t_option = FALSE;
198 for (p = modif; *p; p++) {
199 switch(*p) {
200 case 'b':
201 size = sizeof(char);
202 break;
203 case 'h':
204 size = sizeof(short);
205 break;
206 case 'l':
207 size = sizeof(long);
208 break;
209 case 'u':
210 *u_option = TRUE;
211 break;
212 case 't':
213 *t_option = TRUE;
214 break;
215 }
216 }
217 return(size);
218 }
219
220 boolean_t
221 db_unary(db_expr_t *valuep)
222 {
223 int t;
224 int size;
225 boolean_t u_opt, t_opt;
226 task_t task;
227 extern task_t db_default_task;
228
229 t = db_read_token();
230 if (t == tMINUS) {
231 if (!db_unary(valuep)) {
232 db_error("Expression syntax error after '-'\n");
233 /*NOTREACHED*/
234 }
235 *valuep = -*valuep;
236 return (TRUE);
237 }
238 if (t == tSTAR) {
239 /* indirection */
240 if (!db_unary(valuep)) {
241 db_error("Expression syntax error after '*'\n");
242 /*NOTREACHED*/
243 }
244 task = TASK_NULL;
245 size = sizeof(db_addr_t);
246 u_opt = FALSE;
247 t = db_read_token();
248 if (t == tIDENT && db_tok_string[0] == ':') {
249 size = db_size_option(&db_tok_string[1], &u_opt, &t_opt);
250 if (t_opt)
251 task = db_default_task;
252 } else
253 db_unread_token(t);
254 *valuep = db_get_task_value((db_addr_t)*valuep, size, !u_opt, task);
255 return (TRUE);
256 }
257 if (t == tEXCL) {
258 if (!db_unary(valuep)) {
259 db_error("Expression syntax error after '!'\n");
260 /*NOTREACHED*/
261 }
262 *valuep = (!(*valuep));
263 return (TRUE);
264 }
265 db_unread_token(t);
266 return (db_term(valuep));
267 }
268
269 boolean_t
270 db_mult_expr(db_expr_t *valuep)
271 {
272 db_expr_t lhs, rhs;
273 int t;
274 char c;
275
276 if (!db_unary(&lhs))
277 return (FALSE);
278
279 t = db_read_token();
280 while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH
281 || t == tBIT_AND) {
282 c = db_tok_string[0];
283 if (!db_term(&rhs)) {
284 db_printf("Expression syntax error after '%c'\n", c);
285 db_error(0);
286 /*NOTREACHED*/
287 }
288 switch(t) {
289 case tSTAR:
290 lhs *= rhs;
291 break;
292 case tBIT_AND:
293 lhs &= rhs;
294 break;
295 default:
296 if (rhs == 0) {
297 db_error("Divide by 0\n");
298 /*NOTREACHED*/
299 }
300 if (t == tSLASH)
301 lhs /= rhs;
302 else if (t == tPCT)
303 lhs %= rhs;
304 else
305 lhs = ((lhs+rhs-1)/rhs)*rhs;
306 }
307 t = db_read_token();
308 }
309 db_unread_token(t);
310 *valuep = lhs;
311 return (TRUE);
312 }
313
314 boolean_t
315 db_add_expr(db_expr_t *valuep)
316 {
317 db_expr_t lhs, rhs;
318 int t;
319 char c;
320
321 if (!db_mult_expr(&lhs))
322 return (FALSE);
323
324 t = db_read_token();
325 while (t == tPLUS || t == tMINUS || t == tBIT_OR) {
326 c = db_tok_string[0];
327 if (!db_mult_expr(&rhs)) {
328 db_printf("Expression syntax error after '%c'\n", c);
329 db_error(0);
330 /*NOTREACHED*/
331 }
332 if (t == tPLUS)
333 lhs += rhs;
334 else if (t == tMINUS)
335 lhs -= rhs;
336 else
337 lhs |= rhs;
338 t = db_read_token();
339 }
340 db_unread_token(t);
341 *valuep = lhs;
342 return (TRUE);
343 }
344
345 boolean_t
346 db_shift_expr(db_expr_t *valuep)
347 {
348 db_expr_t lhs, rhs;
349 int t;
350
351 if (!db_add_expr(&lhs))
352 return (FALSE);
353
354 t = db_read_token();
355 while (t == tSHIFT_L || t == tSHIFT_R) {
356 if (!db_add_expr(&rhs)) {
357 db_printf("Expression syntax error after \"%s\"\n",
358 (t == tSHIFT_L)? "<<": ">>");
359 db_error(0);
360 /*NOTREACHED*/
361 }
362 if (rhs < 0) {
363 db_error("Negative shift amount\n");
364 /*NOTREACHED*/
365 }
366 if (t == tSHIFT_L)
367 lhs <<= rhs;
368 else {
369 /* Shift right is unsigned */
370 lhs = (uint64_t) lhs >> rhs;
371 }
372 t = db_read_token();
373 }
374 db_unread_token(t);
375 *valuep = lhs;
376 return (TRUE);
377 }
378
379 boolean_t
380 db_logical_relation_expr(db_expr_t *valuep)
381 {
382 db_expr_t lhs, rhs;
383 int t;
384 char op[3];
385
386 if (!db_shift_expr(&lhs))
387 return(FALSE);
388
389 t = db_read_token();
390 while (t == tLOG_EQ || t == tLOG_NOT_EQ
391 || t == tGREATER || t == tGREATER_EQ
392 || t == tLESS || t == tLESS_EQ) {
393 op[0] = db_tok_string[0];
394 op[1] = db_tok_string[1];
395 op[2] = 0;
396 if (!db_shift_expr(&rhs)) {
397 db_printf("Expression syntax error after \"%s\"\n", op);
398 db_error(0);
399 /*NOTREACHED*/
400 }
401 switch(t) {
402 case tLOG_EQ:
403 lhs = (lhs == rhs);
404 break;
405 case tLOG_NOT_EQ:
406 lhs = (lhs != rhs);
407 break;
408 case tGREATER:
409 lhs = (lhs > rhs);
410 break;
411 case tGREATER_EQ:
412 lhs = (lhs >= rhs);
413 break;
414 case tLESS:
415 lhs = (lhs < rhs);
416 break;
417 case tLESS_EQ:
418 lhs = (lhs <= rhs);
419 break;
420 }
421 t = db_read_token();
422 }
423 db_unread_token(t);
424 *valuep = lhs;
425 return (TRUE);
426 }
427
428 boolean_t
429 db_logical_and_expr(db_expr_t *valuep)
430 {
431 db_expr_t lhs, rhs;
432 int t;
433
434 if (!db_logical_relation_expr(&lhs))
435 return(FALSE);
436
437 t = db_read_token();
438 while (t == tLOG_AND) {
439 if (!db_logical_relation_expr(&rhs)) {
440 db_error("Expression syntax error after \"&&\"\n");
441 /*NOTREACHED*/
442 }
443 lhs = (lhs && rhs);
444 t = db_read_token();
445 }
446 db_unread_token(t);
447 *valuep = lhs;
448 return (TRUE);
449 }
450
451 boolean_t
452 db_logical_or_expr(db_expr_t *valuep)
453 {
454 db_expr_t lhs, rhs;
455 int t;
456
457 if (!db_logical_and_expr(&lhs))
458 return(FALSE);
459
460 t = db_read_token();
461 while (t == tLOG_OR) {
462 if (!db_logical_and_expr(&rhs)) {
463 db_error("Expression syntax error after \"||\"\n");
464 /*NOTREACHED*/
465 }
466 lhs = (lhs || rhs);
467 t = db_read_token();
468 }
469 db_unread_token(t);
470 *valuep = lhs;
471 return (TRUE);
472 }
473
474 int
475 db_expression(db_expr_t *valuep)
476 {
477 return (db_logical_or_expr(valuep));
478 }