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