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