xnu-792.21.3.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_OSREFERENCE_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. 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.
14 *
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
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
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 */
78 boolean_t db_term(db_expr_t *valuep);
79 boolean_t db_unary(db_expr_t *valuep);
80 boolean_t db_mult_expr(db_expr_t *valuep);
81 boolean_t db_add_expr(db_expr_t *valuep);
82 boolean_t db_shift_expr(db_expr_t *valuep);
83 boolean_t db_logical_relation_expr(db_expr_t *valuep);
84 boolean_t db_logical_and_expr(db_expr_t *valuep);
85 boolean_t db_logical_or_expr(db_expr_t *valuep);
86
87
88 /* try to interpret unknown symbols as hexadecimal constants */
89 int db_allow_unprefixed_hexa = 1;
90
91 boolean_t
92 db_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;
106 db_expr_t value;
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 {
127 *valuep = value;
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 {
170 static db_tok_offset = 0;
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
192 int
193 db_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
225 boolean_t
226 db_unary(db_expr_t *valuep)
227 {
228 int t;
229 int size;
230 boolean_t u_opt, t_opt;
231 task_t task;
232 extern task_t db_default_task;
233
234 t = db_read_token();
235 if (t == tMINUS) {
236 if (!db_unary(valuep)) {
237 db_error("Expression syntax error after '-'\n");
238 /*NOTREACHED*/
239 }
240 *valuep = -*valuep;
241 return (TRUE);
242 }
243 if (t == tSTAR) {
244 /* indirection */
245 if (!db_unary(valuep)) {
246 db_error("Expression syntax error after '*'\n");
247 /*NOTREACHED*/
248 }
249 task = TASK_NULL;
250 size = sizeof(db_addr_t);
251 u_opt = FALSE;
252 t = db_read_token();
253 if (t == tIDENT && db_tok_string[0] == ':') {
254 size = db_size_option(&db_tok_string[1], &u_opt, &t_opt);
255 if (t_opt)
256 task = db_default_task;
257 } else
258 db_unread_token(t);
259 *valuep = db_get_task_value((db_addr_t)*valuep, size, !u_opt, task);
260 return (TRUE);
261 }
262 if (t == tEXCL) {
263 if (!db_unary(valuep)) {
264 db_error("Expression syntax error after '!'\n");
265 /*NOTREACHED*/
266 }
267 *valuep = (!(*valuep));
268 return (TRUE);
269 }
270 db_unread_token(t);
271 return (db_term(valuep));
272 }
273
274 boolean_t
275 db_mult_expr(db_expr_t *valuep)
276 {
277 db_expr_t lhs, rhs;
278 int t;
279 char c;
280
281 if (!db_unary(&lhs))
282 return (FALSE);
283
284 t = db_read_token();
285 while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH
286 || t == tBIT_AND) {
287 c = db_tok_string[0];
288 if (!db_term(&rhs)) {
289 db_printf("Expression syntax error after '%c'\n", c);
290 db_error(0);
291 /*NOTREACHED*/
292 }
293 switch(t) {
294 case tSTAR:
295 lhs *= rhs;
296 break;
297 case tBIT_AND:
298 lhs &= rhs;
299 break;
300 default:
301 if (rhs == 0) {
302 db_error("Divide by 0\n");
303 /*NOTREACHED*/
304 }
305 if (t == tSLASH)
306 lhs /= rhs;
307 else if (t == tPCT)
308 lhs %= rhs;
309 else
310 lhs = ((lhs+rhs-1)/rhs)*rhs;
311 }
312 t = db_read_token();
313 }
314 db_unread_token(t);
315 *valuep = lhs;
316 return (TRUE);
317 }
318
319 boolean_t
320 db_add_expr(db_expr_t *valuep)
321 {
322 db_expr_t lhs, rhs;
323 int t;
324 char c;
325
326 if (!db_mult_expr(&lhs))
327 return (FALSE);
328
329 t = db_read_token();
330 while (t == tPLUS || t == tMINUS || t == tBIT_OR) {
331 c = db_tok_string[0];
332 if (!db_mult_expr(&rhs)) {
333 db_printf("Expression syntax error after '%c'\n", c);
334 db_error(0);
335 /*NOTREACHED*/
336 }
337 if (t == tPLUS)
338 lhs += rhs;
339 else if (t == tMINUS)
340 lhs -= rhs;
341 else
342 lhs |= rhs;
343 t = db_read_token();
344 }
345 db_unread_token(t);
346 *valuep = lhs;
347 return (TRUE);
348 }
349
350 boolean_t
351 db_shift_expr(db_expr_t *valuep)
352 {
353 db_expr_t lhs, rhs;
354 int t;
355
356 if (!db_add_expr(&lhs))
357 return (FALSE);
358
359 t = db_read_token();
360 while (t == tSHIFT_L || t == tSHIFT_R) {
361 if (!db_add_expr(&rhs)) {
362 db_printf("Expression syntax error after \"%s\"\n",
363 (t == tSHIFT_L)? "<<": ">>");
364 db_error(0);
365 /*NOTREACHED*/
366 }
367 if (rhs < 0) {
368 db_error("Negative shift amount\n");
369 /*NOTREACHED*/
370 }
371 if (t == tSHIFT_L)
372 lhs <<= rhs;
373 else {
374 /* Shift right is unsigned */
375 lhs = (uint64_t) lhs >> rhs;
376 }
377 t = db_read_token();
378 }
379 db_unread_token(t);
380 *valuep = lhs;
381 return (TRUE);
382 }
383
384 boolean_t
385 db_logical_relation_expr(db_expr_t *valuep)
386 {
387 db_expr_t lhs, rhs;
388 int t;
389 char op[3];
390
391 if (!db_shift_expr(&lhs))
392 return(FALSE);
393
394 t = db_read_token();
395 while (t == tLOG_EQ || t == tLOG_NOT_EQ
396 || t == tGREATER || t == tGREATER_EQ
397 || t == tLESS || t == tLESS_EQ) {
398 op[0] = db_tok_string[0];
399 op[1] = db_tok_string[1];
400 op[2] = 0;
401 if (!db_shift_expr(&rhs)) {
402 db_printf("Expression syntax error after \"%s\"\n", op);
403 db_error(0);
404 /*NOTREACHED*/
405 }
406 switch(t) {
407 case tLOG_EQ:
408 lhs = (lhs == rhs);
409 break;
410 case tLOG_NOT_EQ:
411 lhs = (lhs != rhs);
412 break;
413 case tGREATER:
414 lhs = (lhs > rhs);
415 break;
416 case tGREATER_EQ:
417 lhs = (lhs >= rhs);
418 break;
419 case tLESS:
420 lhs = (lhs < rhs);
421 break;
422 case tLESS_EQ:
423 lhs = (lhs <= rhs);
424 break;
425 }
426 t = db_read_token();
427 }
428 db_unread_token(t);
429 *valuep = lhs;
430 return (TRUE);
431 }
432
433 boolean_t
434 db_logical_and_expr(db_expr_t *valuep)
435 {
436 db_expr_t lhs, rhs;
437 int t;
438
439 if (!db_logical_relation_expr(&lhs))
440 return(FALSE);
441
442 t = db_read_token();
443 while (t == tLOG_AND) {
444 if (!db_logical_relation_expr(&rhs)) {
445 db_error("Expression syntax error after \"&&\"\n");
446 /*NOTREACHED*/
447 }
448 lhs = (lhs && rhs);
449 t = db_read_token();
450 }
451 db_unread_token(t);
452 *valuep = lhs;
453 return (TRUE);
454 }
455
456 boolean_t
457 db_logical_or_expr(db_expr_t *valuep)
458 {
459 db_expr_t lhs, rhs;
460 int t;
461
462 if (!db_logical_and_expr(&lhs))
463 return(FALSE);
464
465 t = db_read_token();
466 while (t == tLOG_OR) {
467 if (!db_logical_and_expr(&rhs)) {
468 db_error("Expression syntax error after \"||\"\n");
469 /*NOTREACHED*/
470 }
471 lhs = (lhs || rhs);
472 t = db_read_token();
473 }
474 db_unread_token(t);
475 *valuep = lhs;
476 return (TRUE);
477 }
478
479 int
480 db_expression(db_expr_t *valuep)
481 {
482 return (db_logical_or_expr(valuep));
483 }