]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_expr.c
xnu-344.23.tar.gz
[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 * 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 * HISTORY
27 *
28 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
29 * Import of Mac OS X kernel (~semeria)
30 *
31 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
32 * Import of OSF Mach kernel (~mburg)
33 *
34 * Revision 1.2.19.1 1997/03/27 18:46:35 barbou
35 * ri-osc CR1561: make operators "logical and", "logical or"
36 * lex correctly.
37 * [1995/09/20 15:26:38 bolinger]
38 * [97/02/25 barbou]
39 *
40 * Revision 1.2.10.2 1995/01/06 19:10:13 devrcs
41 * mk6 CR668 - 1.3b26 merge
42 * * Revision 1.2.3.5 1994/05/06 18:39:16 tmt
43 * Merged osc1.3dec/shared with osc1.3b19
44 * Merge Alpha changes into osc1.312b source code.
45 * 64bit cleanup.
46 * * End1.3merge
47 * [1994/11/04 08:49:27 dwm]
48 *
49 * Revision 1.2.10.1 1994/09/23 01:19:06 ezf
50 * change marker to not FREE
51 * [1994/09/22 21:09:53 ezf]
52 *
53 * Revision 1.2.3.3 1993/07/27 18:27:15 elliston
54 * Add ANSI prototypes. CR #9523.
55 * [1993/07/27 18:11:36 elliston]
56 *
57 * Revision 1.2.3.2 1993/06/09 02:20:06 gm
58 * Added to OSF/1 R1.3 from NMK15.0.
59 * [1993/06/02 20:56:16 jeffc]
60 *
61 * Revision 1.2 1993/04/19 16:02:09 devrcs
62 * Allow unprefixed (0x) hexadecimal constants starting by a letter:
63 * unknown symbols are tentatively interpreted as hexadecimal constants,
64 * and ambiguities are reported.
65 * [93/03/24 barbou]
66 *
67 * Changes from mk78:
68 * Removed unused variable from db_unary().
69 * [92/05/16 jfriedl]
70 * [93/02/02 bruel]
71 *
72 * Added string format arguments [barbou@gr.osf.org]
73 * [92/12/03 bernadat]
74 *
75 * Revision 1.1 1992/09/30 02:01:04 robert
76 * Initial revision
77 *
78 * $EndLog$
79 */
80 /* CMU_HIST */
81 /*
82 * Revision 2.5 91/10/09 15:59:46 af
83 * Revision 2.4.3.1 91/10/05 13:06:04 jeffreyh
84 * Added relational expression etc. to support condition expression.
85 * Supported modifier after indirect expression to specify size,
86 * sign extention and non current task space indirection.
87 * Changed error messages to print more information.
88 * [91/08/29 tak]
89 *
90 * Revision 2.4.3.1 91/10/05 13:06:04 jeffreyh
91 * Added relational expression etc. to support condition expression.
92 * Supported modifier after indirect expression to specify size,
93 * sign extention and non current task space indirection.
94 * Changed error messages to print more information.
95 * [91/08/29 tak]
96 *
97 * Revision 2.4 91/05/14 15:33:45 mrt
98 * Correcting copyright
99 *
100 * Revision 2.3 91/02/05 17:06:25 mrt
101 * Changed to new Mach copyright
102 * [91/01/31 16:17:46 mrt]
103 *
104 * Revision 2.2 90/08/27 21:50:57 dbg
105 * Use '..' instead of '$$' for db_prev.
106 * Use '+' for db_next.
107 * [90/08/22 dbg]
108 *
109 * Allow repeated unary operators.
110 * [90/08/20 dbg]
111 *
112 * Reflected back rename of db_symbol_value->db_value_of_name
113 * [90/08/20 af]
114 * Reduce lint.
115 * [90/08/07 dbg]
116 * Created.
117 * [90/07/25 dbg]
118 *
119 */
120 /* CMU_ENDHIST */
121 /*
122 * Mach Operating System
123 * Copyright (c) 1991,1990 Carnegie Mellon University
124 * All Rights Reserved.
125 *
126 * Permission to use, copy, modify and distribute this software and its
127 * documentation is hereby granted, provided that both the copyright
128 * notice and this permission notice appear in all copies of the
129 * software, derivative works or modified versions, and any portions
130 * thereof, and that both notices appear in supporting documentation.
131 *
132 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
133 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
134 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
135 *
136 * Carnegie Mellon requests users of this software to return to
137 *
138 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
139 * School of Computer Science
140 * Carnegie Mellon University
141 * Pittsburgh PA 15213-3890
142 *
143 * any improvements or extensions that they make and grant Carnegie Mellon
144 * the rights to redistribute these changes.
145 */
146 /*
147 */
148 /*
149 * Author: David B. Golub, Carnegie Mellon University
150 * Date: 7/90
151 */
152
153 #include <mach/boolean.h>
154 #include <machine/db_machdep.h>
155 #include <ddb/db_access.h>
156 #include <ddb/db_command.h>
157 #include <ddb/db_expr.h>
158 #include <ddb/db_lex.h>
159 #include <ddb/db_output.h> /* For db_printf() */
160 #include <ddb/db_sym.h>
161 #include <ddb/db_variables.h>
162 #include <kern/task.h>
163
164
165
166 /* Prototypes for functions local to this file. XXX -- should be static!
167 */
168 boolean_t db_term(db_expr_t *valuep);
169 boolean_t db_unary(db_expr_t *valuep);
170 boolean_t db_mult_expr(db_expr_t *valuep);
171 boolean_t db_add_expr(db_expr_t *valuep);
172 boolean_t db_shift_expr(db_expr_t *valuep);
173 boolean_t db_logical_relation_expr(db_expr_t *valuep);
174 boolean_t db_logical_and_expr(db_expr_t *valuep);
175 boolean_t db_logical_or_expr(db_expr_t *valuep);
176
177
178 /* try to interpret unknown symbols as hexadecimal constants */
179 int db_allow_unprefixed_hexa = 1;
180
181 boolean_t
182 db_term(db_expr_t *valuep)
183 {
184 int t;
185 boolean_t valid_symbol = FALSE;
186 boolean_t valid_hexa = FALSE;
187
188 switch(t = db_read_token()) {
189 case tIDENT:
190 if (db_value_of_name(db_tok_string, valuep)) {
191 valid_symbol = TRUE;
192 }
193 if (db_allow_unprefixed_hexa && db_radix == 16 &&
194 db_tok_string) {
195 char *cp;
196 int value;
197
198 value = 0;
199 valid_hexa = TRUE;
200 for (cp = db_tok_string; *cp; cp++) {
201 if (*cp >= 'a' && *cp <= 'f') {
202 value = value * 16 + 10 + (*cp - 'a');
203 } else if (*cp >= 'A' && *cp <= 'F') {
204 value = value * 16 + 10 + (*cp - 'A');
205 } else if (*cp >= '0' && *cp <= '9') {
206 value = value * 16 + (*cp - '0');
207 } else {
208 valid_hexa = FALSE;
209 break;
210 }
211 }
212 if (valid_hexa) {
213 if (valid_symbol) {
214 db_printf("Ambiguous constant %x used as a symbol\n",
215 value);
216 } else {
217 *valuep = (db_expr_t)value;
218 }
219 }
220 }
221 if (!valid_symbol && !valid_hexa) {
222 db_printf("Symbol \"%s\" not found\n", db_tok_string);
223 db_error(0);
224 /*NOTREACHED*/
225 }
226 return (TRUE);
227 case tNUMBER:
228 *valuep = /*(db_expr_t)*/db_tok_number;
229 return (TRUE);
230 case tDOT:
231 *valuep = (db_expr_t)db_dot;
232 return (TRUE);
233 case tDOTDOT:
234 *valuep = (db_expr_t)db_prev;
235 return (TRUE);
236 case tPLUS:
237 *valuep = (db_expr_t) db_next;
238 return (TRUE);
239 case tQUOTE:
240 *valuep = (db_expr_t)db_last_addr;
241 return (TRUE);
242 case tDOLLAR:
243 if (!db_get_variable(valuep))
244 return (FALSE);
245 return (TRUE);
246 case tLPAREN:
247 if (!db_expression(valuep)) {
248 db_error("Unmached ()s\n");
249 /*NOTREACHED*/
250 }
251 t = db_read_token();
252 if (t != tRPAREN) {
253 db_printf("')' expected at \"%s...\"\n", db_tok_string);
254 db_error(0);
255 /*NOTREACHED*/
256 }
257 return (TRUE);
258 case tSTRING:
259 {
260 static db_tok_offset = 0;
261 char *sp, *cp;
262
263 sp = (char *)db_tok_string + db_tok_offset;
264 *valuep = *(int *)sp;
265 for (cp = sp;
266 *cp && cp < sp + sizeof (int);
267 cp++);
268 if (cp == sp + sizeof (int) && *cp) {
269 db_tok_offset += sizeof (int);
270 db_unread_token(t);
271 } else {
272 db_tok_offset = 0;
273 }
274 return (TRUE);
275 }
276 default:
277 db_unread_token(t);
278 return (FALSE);
279 }
280 }
281
282 int
283 db_size_option(
284 char *modif,
285 boolean_t *u_option,
286 boolean_t *t_option)
287 {
288 register char *p;
289 int size = sizeof(int);
290
291 *u_option = FALSE;
292 *t_option = FALSE;
293 for (p = modif; *p; p++) {
294 switch(*p) {
295 case 'b':
296 size = sizeof(char);
297 break;
298 case 'h':
299 size = sizeof(short);
300 break;
301 case 'l':
302 size = sizeof(long);
303 break;
304 case 'u':
305 *u_option = TRUE;
306 break;
307 case 't':
308 *t_option = TRUE;
309 break;
310 }
311 }
312 return(size);
313 }
314
315 boolean_t
316 db_unary(db_expr_t *valuep)
317 {
318 int t;
319 int size;
320 boolean_t u_opt, t_opt;
321 task_t task;
322 extern task_t db_default_task;
323
324 t = db_read_token();
325 if (t == tMINUS) {
326 if (!db_unary(valuep)) {
327 db_error("Expression syntax error after '-'\n");
328 /*NOTREACHED*/
329 }
330 *valuep = -*valuep;
331 return (TRUE);
332 }
333 if (t == tSTAR) {
334 /* indirection */
335 if (!db_unary(valuep)) {
336 db_error("Expression syntax error after '*'\n");
337 /*NOTREACHED*/
338 }
339 task = TASK_NULL;
340 size = sizeof(db_addr_t);
341 u_opt = FALSE;
342 t = db_read_token();
343 if (t == tIDENT && db_tok_string[0] == ':') {
344 size = db_size_option(&db_tok_string[1], &u_opt, &t_opt);
345 if (t_opt)
346 task = db_default_task;
347 } else
348 db_unread_token(t);
349 *valuep = db_get_task_value((db_addr_t)*valuep, size, !u_opt, task);
350 return (TRUE);
351 }
352 if (t == tEXCL) {
353 if (!db_unary(valuep)) {
354 db_error("Expression syntax error after '!'\n");
355 /*NOTREACHED*/
356 }
357 *valuep = (!(*valuep));
358 return (TRUE);
359 }
360 db_unread_token(t);
361 return (db_term(valuep));
362 }
363
364 boolean_t
365 db_mult_expr(db_expr_t *valuep)
366 {
367 db_expr_t lhs, rhs;
368 int t;
369 char c;
370
371 if (!db_unary(&lhs))
372 return (FALSE);
373
374 t = db_read_token();
375 while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH
376 || t == tBIT_AND) {
377 c = db_tok_string[0];
378 if (!db_term(&rhs)) {
379 db_printf("Expression syntax error after '%c'\n", c);
380 db_error(0);
381 /*NOTREACHED*/
382 }
383 switch(t) {
384 case tSTAR:
385 lhs *= rhs;
386 break;
387 case tBIT_AND:
388 lhs &= rhs;
389 break;
390 default:
391 if (rhs == 0) {
392 db_error("Divide by 0\n");
393 /*NOTREACHED*/
394 }
395 if (t == tSLASH)
396 lhs /= rhs;
397 else if (t == tPCT)
398 lhs %= rhs;
399 else
400 lhs = ((lhs+rhs-1)/rhs)*rhs;
401 }
402 t = db_read_token();
403 }
404 db_unread_token(t);
405 *valuep = lhs;
406 return (TRUE);
407 }
408
409 boolean_t
410 db_add_expr(db_expr_t *valuep)
411 {
412 db_expr_t lhs, rhs;
413 int t;
414 char c;
415
416 if (!db_mult_expr(&lhs))
417 return (FALSE);
418
419 t = db_read_token();
420 while (t == tPLUS || t == tMINUS || t == tBIT_OR) {
421 c = db_tok_string[0];
422 if (!db_mult_expr(&rhs)) {
423 db_printf("Expression syntax error after '%c'\n", c);
424 db_error(0);
425 /*NOTREACHED*/
426 }
427 if (t == tPLUS)
428 lhs += rhs;
429 else if (t == tMINUS)
430 lhs -= rhs;
431 else
432 lhs |= rhs;
433 t = db_read_token();
434 }
435 db_unread_token(t);
436 *valuep = lhs;
437 return (TRUE);
438 }
439
440 boolean_t
441 db_shift_expr(db_expr_t *valuep)
442 {
443 db_expr_t lhs, rhs;
444 int t;
445
446 if (!db_add_expr(&lhs))
447 return (FALSE);
448
449 t = db_read_token();
450 while (t == tSHIFT_L || t == tSHIFT_R) {
451 if (!db_add_expr(&rhs)) {
452 db_printf("Expression syntax error after \"%s\"\n",
453 (t == tSHIFT_L)? "<<": ">>");
454 db_error(0);
455 /*NOTREACHED*/
456 }
457 if (rhs < 0) {
458 db_error("Negative shift amount\n");
459 /*NOTREACHED*/
460 }
461 if (t == tSHIFT_L)
462 lhs <<= rhs;
463 else {
464 /* Shift right is unsigned */
465 lhs = (natural_t) lhs >> rhs;
466 }
467 t = db_read_token();
468 }
469 db_unread_token(t);
470 *valuep = lhs;
471 return (TRUE);
472 }
473
474 boolean_t
475 db_logical_relation_expr(db_expr_t *valuep)
476 {
477 db_expr_t lhs, rhs;
478 int t;
479 char op[3];
480
481 if (!db_shift_expr(&lhs))
482 return(FALSE);
483
484 t = db_read_token();
485 while (t == tLOG_EQ || t == tLOG_NOT_EQ
486 || t == tGREATER || t == tGREATER_EQ
487 || t == tLESS || t == tLESS_EQ) {
488 op[0] = db_tok_string[0];
489 op[1] = db_tok_string[1];
490 op[2] = 0;
491 if (!db_shift_expr(&rhs)) {
492 db_printf("Expression syntax error after \"%s\"\n", op);
493 db_error(0);
494 /*NOTREACHED*/
495 }
496 switch(t) {
497 case tLOG_EQ:
498 lhs = (lhs == rhs);
499 break;
500 case tLOG_NOT_EQ:
501 lhs = (lhs != rhs);
502 break;
503 case tGREATER:
504 lhs = (lhs > rhs);
505 break;
506 case tGREATER_EQ:
507 lhs = (lhs >= rhs);
508 break;
509 case tLESS:
510 lhs = (lhs < rhs);
511 break;
512 case tLESS_EQ:
513 lhs = (lhs <= rhs);
514 break;
515 }
516 t = db_read_token();
517 }
518 db_unread_token(t);
519 *valuep = lhs;
520 return (TRUE);
521 }
522
523 boolean_t
524 db_logical_and_expr(db_expr_t *valuep)
525 {
526 db_expr_t lhs, rhs;
527 int t;
528
529 if (!db_logical_relation_expr(&lhs))
530 return(FALSE);
531
532 t = db_read_token();
533 while (t == tLOG_AND) {
534 if (!db_logical_relation_expr(&rhs)) {
535 db_error("Expression syntax error after \"&&\"\n");
536 /*NOTREACHED*/
537 }
538 lhs = (lhs && rhs);
539 t = db_read_token();
540 }
541 db_unread_token(t);
542 *valuep = lhs;
543 return (TRUE);
544 }
545
546 boolean_t
547 db_logical_or_expr(db_expr_t *valuep)
548 {
549 db_expr_t lhs, rhs;
550 int t;
551
552 if (!db_logical_and_expr(&lhs))
553 return(FALSE);
554
555 t = db_read_token();
556 while (t == tLOG_OR) {
557 if (!db_logical_and_expr(&rhs)) {
558 db_error("Expression syntax error after \"||\"\n");
559 /*NOTREACHED*/
560 }
561 lhs = (lhs || rhs);
562 t = db_read_token();
563 }
564 db_unread_token(t);
565 *valuep = lhs;
566 return (TRUE);
567 }
568
569 int
570 db_expression(db_expr_t *valuep)
571 {
572 return (db_logical_or_expr(valuep));
573 }