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