2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1991,1990 Carnegie Mellon University
28 * All Rights Reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon
48 * the rights to redistribute these changes.
53 * Author: David B. Golub, Carnegie Mellon University
57 #include <machine/db_machdep.h>
58 #include <string.h> /* For strcpy() */
60 #include <ddb/db_lex.h>
61 #include <ddb/db_variables.h>
62 #include <ddb/db_task_thread.h>
63 #include <ddb/db_sym.h>
64 #include <ddb/db_command.h>
65 #include <ddb/db_expr.h>
66 #include <ddb/db_macro.h>
67 #include <ddb/db_output.h> /* For db_printf() */
69 extern db_expr_t db_radix
;
70 extern db_expr_t db_max_width
;
71 extern db_expr_t db_tab_stop_width
;
72 extern db_expr_t db_max_line
;
73 extern db_expr_t db_auto_wrap
;
74 extern db_expr_t db_macro_level
;
75 extern db_expr_t db_auto_completion
;
77 #define DB_NWORK 32 /* number of work variable */
79 db_expr_t db_work
[DB_NWORK
]; /* work variable */
81 struct db_variable db_vars
[] = {
82 { "maxoff", (db_expr_t
*)&db_maxoff
, FCN_NULL
},
83 { "autowrap", &db_auto_wrap
, FCN_NULL
},
84 { "completion", &db_auto_completion
, FCN_NULL
},
85 { "maxwidth", &db_max_width
, FCN_NULL
},
86 { "radix", &db_radix
, FCN_NULL
},
87 { "tabstops", &db_tab_stop_width
, FCN_NULL
},
88 { "lines", &db_max_line
, FCN_NULL
},
89 { "thr_act", 0, db_set_default_act
},
90 { "task", 0, db_get_task_act
,
92 { "work", &db_work
[0], FCN_NULL
,
93 1, 1, 0, DB_NWORK
-1 },
94 { "arg", 0, db_arg_variable
,
95 1, 1, 1, DB_MACRO_NARGS
,
96 1, 0, DB_MACRO_LEVEL
-1, (int *)&db_macro_level
},
98 struct db_variable
*db_evars
= db_vars
+ sizeof(db_vars
)/sizeof(db_vars
[0]);
102 /* Prototypes for functions local to this file.
105 static char *db_get_suffix(
106 register char *suffix
,
107 short *suffix_value
);
109 static boolean_t
db_cmp_variable_name(
110 struct db_variable
*vp
,
112 register db_var_aux_param_t ap
);
114 static int db_find_variable(
115 struct db_variable
**varp
,
116 db_var_aux_param_t ap
);
118 static int db_set_variable(db_expr_t value
);
120 void db_list_variable(void);
124 register char *suffix
,
129 for (value
= 0; *suffix
&& *suffix
!= '.' && *suffix
!= ':'; suffix
++) {
130 if (*suffix
< '0' || *suffix
> '9')
132 value
= value
*10 + *suffix
- '0';
134 *suffix_value
= value
;
141 db_cmp_variable_name(
142 struct db_variable
*vp
,
144 register db_var_aux_param_t ap
)
146 register char *var_np
, *np
;
149 for (np
= name
, var_np
= vp
->name
; *var_np
; ) {
150 if (*np
++ != *var_np
++)
153 for (level
= 0; *np
&& *np
!= ':' && level
< vp
->max_level
; level
++){
154 if ((np
= db_get_suffix(np
, &ap
->suffix
[level
])) == 0)
157 if ((*np
&& *np
!= ':') || level
< vp
->min_level
158 || (level
> 0 && (ap
->suffix
[0] < vp
->low
159 || (vp
->high
>= 0 && ap
->suffix
[0] > vp
->high
))))
161 strcpy(ap
->modif
, (*np
)? np
+1: "");
162 ap
->thr_act
= (db_option(ap
->modif
, 't')?db_default_act
: THREAD_NULL
);
164 ap
->hidden_level
= -1;
170 struct db_variable
**varp
,
171 db_var_aux_param_t ap
)
174 struct db_variable
*vp
;
178 for (vp
= db_vars
; vp
< db_evars
; vp
++) {
179 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
184 for (vp
= db_regs
; vp
< db_eregs
; vp
++) {
185 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
190 #if defined(ALTERNATE_REGISTER_DEFS)
191 for (vp
= db_altregs
; vp
< db_ealtregs
; vp
++) {
192 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
197 #endif /* defined(ALTERNATE_REGISTER_DEFS) */
199 db_printf("Unknown variable \"$%s\"\n", db_tok_string
);
205 db_get_variable(db_expr_t
*valuep
)
207 struct db_variable
*vp
;
208 struct db_var_aux_param aux_param
;
209 char modif
[TOK_STRING_SIZE
];
211 aux_param
.modif
= modif
;
212 if (!db_find_variable(&vp
, &aux_param
))
215 db_read_write_variable(vp
, valuep
, DB_VAR_GET
, &aux_param
);
221 db_set_variable(db_expr_t value
)
223 struct db_variable
*vp
;
224 struct db_var_aux_param aux_param
;
225 char modif
[TOK_STRING_SIZE
];
227 aux_param
.modif
= modif
;
228 if (!db_find_variable(&vp
, &aux_param
))
231 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
237 db_read_write_variable(
238 struct db_variable
*vp
,
241 db_var_aux_param_t ap
)
243 int (*func
)(struct db_variable
*, db_expr_t
*,int, db_var_aux_param_t
)
245 struct db_var_aux_param aux_param
;
252 ap
->thr_act
= THREAD_NULL
;
254 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
255 db_read_write_variable(vp
, &old_value
, DB_VAR_GET
, ap
);
256 if (func
== FCN_NULL
) {
257 if (rw_flag
== DB_VAR_SET
)
258 vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0] = *valuep
;
260 *valuep
= vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0];
262 (*func
)(vp
, valuep
, rw_flag
, ap
);
263 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
264 db_printf("\t$%s:%s<%#x>\t%#8lln\t=\t%#8lln\n", vp
->name
,
265 ap
->modif
, ap
->thr_act
, (unsigned long long)old_value
, (unsigned long long)*valuep
);
269 db_list_variable(void)
271 register struct db_variable
*new;
272 register struct db_variable
*old
;
273 register struct db_variable
*cur
;
280 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
281 if (cur
->min_level
> 0 || cur
->max_level
> 0) {
282 j
= 3 * (cur
->max_level
- cur
->min_level
+ 1) - 1;
283 if (cur
->max_level
> cur
->min_level
)
287 if ((l
= strlen(cur
->name
) + j
) >= len
)
291 old
= (struct db_variable
*)0;
293 new = (struct db_variable
*)0;
294 for (cur
= db_vars
; cur
< db_evars
; cur
++)
295 if ((new == (struct db_variable
*)0 ||
296 strcmp(cur
->name
, new->name
) < 0) &&
297 (old
== (struct db_variable
*)0 ||
298 strcmp(cur
->name
, old
->name
) > 0))
300 if (new == (struct db_variable
*)0)
302 db_reserve_output_position(len
);
303 db_printf(new->name
);
304 j
= strlen(new->name
);
305 if (new->min_level
> 0) {
309 for (i
= new->min_level
- 1; i
> 0; i
--) {
315 if (new->max_level
> new->min_level
) {
322 i
= new->min_level
+ 1;
324 if (new->max_level
> new->min_level
) {
330 while (i
++ < new->max_level
) {
336 if (new->max_level
> new->min_level
) {
351 struct db_variable
*vp
;
352 struct db_var_aux_param aux_param
;
353 char modif
[TOK_STRING_SIZE
];
355 aux_param
.modif
= modif
;
357 if (t
== tIDENT
&& strcmp("help", db_tok_string
) == 0) {
362 db_error("Variable name should be prefixed with $\n");
365 if (!db_find_variable(&vp
, &aux_param
)) {
366 db_error("Unknown variable\n");
374 if (!db_expression(&value
)) {
375 db_error("No value\n");
378 if ((t
= db_read_token()) == tSEMI_COLON
)
383 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
387 db_show_one_variable(void)
389 struct db_variable
*cur
;
399 struct db_var_aux_param aux_param
;
405 for (cur
= db_vars
; cur
< db_evars
; cur
++)
406 if (db_cmp_variable_name(cur
, db_tok_string
, &aux_param
))
408 if (cur
== db_evars
) {
409 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
410 for (q
= cur
->name
, p
= db_tok_string
; *q
&& *p
== *q
; p
++,q
++)
415 if (cur
== db_evars
) {
416 db_error("Unknown variable\n");
420 for (i
= 0; *p
&& *p
!= ':' && i
< cur
->max_level
; i
++, p
= q
)
421 if ((q
= db_get_suffix(p
, &aux_param
.suffix
[i
])) == 0)
424 if ((*p
&& *p
!= ':') ||
425 (i
> 0 && (aux_param
.suffix
[0] < cur
->low
||
427 aux_param
.suffix
[0] > cur
->high
)))) {
428 db_error("Unknown variable format\n");
432 strcpy(aux_param
.modif
, *p
? p
+ 1 : "");
433 aux_param
.thr_act
= (db_option(aux_param
.modif
, 't') ?
434 db_default_act
: THREAD_NULL
);
437 if (cur
->hidden_level
)
438 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
439 *cur
->hidden_levelp
<= cur
->hidden_high
) {
441 aux_param
.hidden_level
= h
= *cur
->hidden_levelp
;
444 aux_param
.hidden_level
= h
= cur
->hidden_low
;
446 for (k
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->high
;
451 aux_param
.hidden_level
= -1;
453 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
456 if (cur
->min_level
> 0) {
458 for (k
= aux_param
.level
> 0 ?
459 aux_param
.suffix
[0] : cur
->high
; k
> 9; k
/= 10)
463 if (cur
->hidden_level
&& hidden_level
== 0) {
465 for (k
= aux_param
.hidden_level
>= 0 ?
466 aux_param
.hidden_level
: cur
->hidden_high
; k
> 9; k
/= 10)
470 len
= strlen(cur
->name
) + j
;
471 i
= low
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->low
;
474 db_printf(cur
->name
);
475 j
= strlen(cur
->name
);
476 if (cur
->high
>= 0) {
477 if (cur
->min_level
> 0) {
480 for (k
= i
; k
> 9; k
/= 10)
483 if (cur
->hidden_level
&& hidden_level
== 0) {
485 for (k
= i
; k
> 9; k
/= 10)
487 while (sl
++ < slen
) {
491 db_printf("[%d]", h
);
493 for (k
= h
; k
> 9; k
/= 10)
504 aux_param
.suffix
[0] = i
;
505 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
507 db_printf("%#lln", (unsigned long long)*(cur
->valuep
+ i
));
508 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
510 if (name
!= (char *)0 && offset
<= db_maxoff
&&
511 offset
!= *(cur
->valuep
+ i
)) {
512 db_printf("\t%s", name
);
514 db_printf("+%#llr", (unsigned long long)offset
);
520 if (aux_param
.level
> 0 || i
++ == cur
->high
) {
521 if (!cur
->hidden_level
||
523 h
++ == cur
->hidden_high
)
525 aux_param
.hidden_level
= h
;
532 db_show_variable(void)
534 struct db_variable
*cur
;
545 struct db_var_aux_param aux_param
;
549 switch(t
= db_read_token()) {
556 t1
= db_read_token();
558 db_show_one_variable();
561 db_error("Not a variable name after $\n");
566 db_error("Variable name should be prefixed with $\n");
573 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
574 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
577 if (cur
->min_level
> 0) {
579 for (k
= cur
->high
; k
> 9; k
/= 10)
583 if (cur
->hidden_level
&&
584 (*cur
->hidden_levelp
< cur
->hidden_low
||
585 *cur
->hidden_levelp
> cur
->hidden_high
)) {
587 for (k
= cur
->hidden_high
; k
> 9; k
/= 10)
591 if ((l
= strlen(cur
->name
) + j
) >= len
)
595 aux_param
.modif
= "";
597 aux_param
.thr_act
= THREAD_NULL
;
599 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
601 if (cur
->hidden_level
) {
602 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
603 *cur
->hidden_levelp
<= cur
->hidden_high
) {
604 h
= cur
->hidden_low
- 1;
605 aux_param
.hidden_level
= *cur
->hidden_levelp
;
608 aux_param
.hidden_level
= cur
->hidden_low
;
611 for (k
= cur
->high
; k
> 9; k
/= 10)
614 aux_param
.hidden_level
= -1;
616 if (cur
!= db_vars
&& cur
->high
>= 0 &&
617 (cur
->min_level
> 0 || cur
->hidden_level
))
621 db_printf(cur
->name
);
622 j
= strlen(cur
->name
);
623 if (cur
->high
>= 0) {
624 if (cur
->min_level
> 0) {
627 for (k
= i
; k
> 9; k
/= 10)
630 if (cur
->hidden_level
&& h
>= cur
->hidden_low
) {
632 for (k
= i
; k
> 9; k
/= 10)
634 while (sl
++ < slen
) {
638 db_printf("[%d]", h
);
640 for (k
= h
; k
> 9; k
/= 10)
650 aux_param
.suffix
[0] = i
;
651 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
653 db_printf("%#lln", (unsigned long long)*(cur
->valuep
+ i
));
654 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
656 if (name
!= (char *)0 && offset
<= db_maxoff
&&
657 offset
!= *(cur
->valuep
+ i
)) {
658 db_printf("\t%s", name
);
660 db_printf("+%#llr", (unsigned long long)offset
);
666 if (i
++ == cur
->high
) {
667 if (!cur
->hidden_level
|| h
++ == cur
->hidden_high
)
669 aux_param
.hidden_level
= h
;
677 * given a name of a machine register, return a variable pointer to it.
683 register db_variable_t regp
;
685 if ( s
== (char *)0 )
688 for (regp
= db_regs
; regp
< db_eregs
; regp
++) {
689 if ( strcmp( s
, regp
->name
) == 0 )