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