2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
27 * Mach Operating System
28 * Copyright (c) 1991,1990 Carnegie Mellon University
29 * All Rights Reserved.
31 * Permission to use, copy, modify and distribute this software and its
32 * documentation is hereby granted, provided that both the copyright
33 * notice and this permission notice appear in all copies of the
34 * software, derivative works or modified versions, and any portions
35 * thereof, and that both notices appear in supporting documentation.
37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
41 * Carnegie Mellon requests users of this software to return to
43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
44 * School of Computer Science
45 * Carnegie Mellon University
46 * Pittsburgh PA 15213-3890
48 * any improvements or extensions that they make and grant Carnegie Mellon
49 * the rights to redistribute these changes.
54 * Author: David B. Golub, Carnegie Mellon University
58 #include <machine/db_machdep.h>
59 #include <string.h> /* For strcpy() */
61 #include <ddb/db_lex.h>
62 #include <ddb/db_variables.h>
63 #include <ddb/db_task_thread.h>
64 #include <ddb/db_sym.h>
65 #include <ddb/db_command.h>
66 #include <ddb/db_expr.h>
67 #include <ddb/db_macro.h>
68 #include <ddb/db_output.h> /* For db_printf() */
70 extern db_expr_t db_radix
;
71 extern db_expr_t db_max_width
;
72 extern db_expr_t db_tab_stop_width
;
73 extern db_expr_t db_max_line
;
74 extern db_expr_t db_auto_wrap
;
75 extern db_expr_t db_macro_level
;
76 extern db_expr_t db_auto_completion
;
78 #define DB_NWORK 32 /* number of work variable */
80 db_expr_t db_work
[DB_NWORK
]; /* work variable */
82 struct db_variable db_vars
[] = {
83 { "maxoff", (db_expr_t
*)&db_maxoff
, FCN_NULL
},
84 { "autowrap", &db_auto_wrap
, FCN_NULL
},
85 { "completion", &db_auto_completion
, FCN_NULL
},
86 { "maxwidth", &db_max_width
, FCN_NULL
},
87 { "radix", &db_radix
, FCN_NULL
},
88 { "tabstops", &db_tab_stop_width
, FCN_NULL
},
89 { "lines", &db_max_line
, FCN_NULL
},
90 { "thr_act", 0, db_set_default_act
},
91 { "task", 0, db_get_task_act
,
93 { "work", &db_work
[0], FCN_NULL
,
94 1, 1, 0, DB_NWORK
-1 },
95 { "arg", 0, db_arg_variable
,
96 1, 1, 1, DB_MACRO_NARGS
,
97 1, 0, DB_MACRO_LEVEL
-1, (int *)&db_macro_level
},
99 struct db_variable
*db_evars
= db_vars
+ sizeof(db_vars
)/sizeof(db_vars
[0]);
103 /* Prototypes for functions local to this file.
106 static char *db_get_suffix(
107 register char *suffix
,
108 short *suffix_value
);
110 static boolean_t
db_cmp_variable_name(
111 struct db_variable
*vp
,
113 register db_var_aux_param_t ap
);
115 static int db_find_variable(
116 struct db_variable
**varp
,
117 db_var_aux_param_t ap
);
119 static int db_set_variable(db_expr_t value
);
121 void db_list_variable(void);
125 register char *suffix
,
130 for (value
= 0; *suffix
&& *suffix
!= '.' && *suffix
!= ':'; suffix
++) {
131 if (*suffix
< '0' || *suffix
> '9')
133 value
= value
*10 + *suffix
- '0';
135 *suffix_value
= value
;
142 db_cmp_variable_name(
143 struct db_variable
*vp
,
145 register db_var_aux_param_t ap
)
147 register char *var_np
, *np
;
150 for (np
= name
, var_np
= vp
->name
; *var_np
; ) {
151 if (*np
++ != *var_np
++)
154 for (level
= 0; *np
&& *np
!= ':' && level
< vp
->max_level
; level
++){
155 if ((np
= db_get_suffix(np
, &ap
->suffix
[level
])) == 0)
158 if ((*np
&& *np
!= ':') || level
< vp
->min_level
159 || (level
> 0 && (ap
->suffix
[0] < vp
->low
160 || (vp
->high
>= 0 && ap
->suffix
[0] > vp
->high
))))
162 strcpy(ap
->modif
, (*np
)? np
+1: "");
163 ap
->thr_act
= (db_option(ap
->modif
, 't')?db_default_act
: THREAD_NULL
);
165 ap
->hidden_level
= -1;
171 struct db_variable
**varp
,
172 db_var_aux_param_t ap
)
175 struct db_variable
*vp
;
179 for (vp
= db_vars
; vp
< db_evars
; vp
++) {
180 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
185 for (vp
= db_regs
; vp
< db_eregs
; vp
++) {
186 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
191 #if defined(ALTERNATE_REGISTER_DEFS)
192 for (vp
= db_altregs
; vp
< db_ealtregs
; vp
++) {
193 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
198 #endif /* defined(ALTERNATE_REGISTER_DEFS) */
200 db_printf("Unknown variable \"$%s\"\n", db_tok_string
);
206 db_get_variable(db_expr_t
*valuep
)
208 struct db_variable
*vp
;
209 struct db_var_aux_param aux_param
;
210 char modif
[TOK_STRING_SIZE
];
212 aux_param
.modif
= modif
;
213 if (!db_find_variable(&vp
, &aux_param
))
216 db_read_write_variable(vp
, valuep
, DB_VAR_GET
, &aux_param
);
222 db_set_variable(db_expr_t value
)
224 struct db_variable
*vp
;
225 struct db_var_aux_param aux_param
;
226 char modif
[TOK_STRING_SIZE
];
228 aux_param
.modif
= modif
;
229 if (!db_find_variable(&vp
, &aux_param
))
232 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
238 db_read_write_variable(
239 struct db_variable
*vp
,
242 db_var_aux_param_t ap
)
244 int (*func
)(struct db_variable
*, db_expr_t
*,int, db_var_aux_param_t
)
246 struct db_var_aux_param aux_param
;
253 ap
->thr_act
= THREAD_NULL
;
255 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
256 db_read_write_variable(vp
, &old_value
, DB_VAR_GET
, ap
);
257 if (func
== FCN_NULL
) {
258 if (rw_flag
== DB_VAR_SET
)
259 vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0] = *valuep
;
261 *valuep
= vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0];
263 (*func
)(vp
, valuep
, rw_flag
, ap
);
264 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
265 db_printf("\t$%s:%s<%#x>\t%#8lln\t=\t%#8lln\n", vp
->name
,
266 ap
->modif
, ap
->thr_act
, (unsigned long long)old_value
, (unsigned long long)*valuep
);
270 db_list_variable(void)
272 register struct db_variable
*new;
273 register struct db_variable
*old
;
274 register struct db_variable
*cur
;
281 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
282 if (cur
->min_level
> 0 || cur
->max_level
> 0) {
283 j
= 3 * (cur
->max_level
- cur
->min_level
+ 1) - 1;
284 if (cur
->max_level
> cur
->min_level
)
288 if ((l
= strlen(cur
->name
) + j
) >= len
)
292 old
= (struct db_variable
*)0;
294 new = (struct db_variable
*)0;
295 for (cur
= db_vars
; cur
< db_evars
; cur
++)
296 if ((new == (struct db_variable
*)0 ||
297 strcmp(cur
->name
, new->name
) < 0) &&
298 (old
== (struct db_variable
*)0 ||
299 strcmp(cur
->name
, old
->name
) > 0))
301 if (new == (struct db_variable
*)0)
303 db_reserve_output_position(len
);
304 db_printf(new->name
);
305 j
= strlen(new->name
);
306 if (new->min_level
> 0) {
310 for (i
= new->min_level
- 1; i
> 0; i
--) {
316 if (new->max_level
> new->min_level
) {
323 i
= new->min_level
+ 1;
325 if (new->max_level
> new->min_level
) {
331 while (i
++ < new->max_level
) {
337 if (new->max_level
> new->min_level
) {
352 struct db_variable
*vp
;
353 struct db_var_aux_param aux_param
;
354 char modif
[TOK_STRING_SIZE
];
356 aux_param
.modif
= modif
;
358 if (t
== tIDENT
&& strcmp("help", db_tok_string
) == 0) {
363 db_error("Variable name should be prefixed with $\n");
366 if (!db_find_variable(&vp
, &aux_param
)) {
367 db_error("Unknown variable\n");
375 if (!db_expression(&value
)) {
376 db_error("No value\n");
379 if ((t
= db_read_token()) == tSEMI_COLON
)
384 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
388 db_show_one_variable(void)
390 struct db_variable
*cur
;
400 struct db_var_aux_param aux_param
;
406 for (cur
= db_vars
; cur
< db_evars
; cur
++)
407 if (db_cmp_variable_name(cur
, db_tok_string
, &aux_param
))
409 if (cur
== db_evars
) {
410 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
411 for (q
= cur
->name
, p
= db_tok_string
; *q
&& *p
== *q
; p
++,q
++)
416 if (cur
== db_evars
) {
417 db_error("Unknown variable\n");
421 for (i
= 0; *p
&& *p
!= ':' && i
< cur
->max_level
; i
++, p
= q
)
422 if ((q
= db_get_suffix(p
, &aux_param
.suffix
[i
])) == 0)
425 if ((*p
&& *p
!= ':') ||
426 (i
> 0 && (aux_param
.suffix
[0] < cur
->low
||
428 aux_param
.suffix
[0] > cur
->high
)))) {
429 db_error("Unknown variable format\n");
433 strcpy(aux_param
.modif
, *p
? p
+ 1 : "");
434 aux_param
.thr_act
= (db_option(aux_param
.modif
, 't') ?
435 db_default_act
: THREAD_NULL
);
438 if (cur
->hidden_level
)
439 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
440 *cur
->hidden_levelp
<= cur
->hidden_high
) {
442 aux_param
.hidden_level
= h
= *cur
->hidden_levelp
;
445 aux_param
.hidden_level
= h
= cur
->hidden_low
;
447 for (k
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->high
;
452 aux_param
.hidden_level
= -1;
454 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
457 if (cur
->min_level
> 0) {
459 for (k
= aux_param
.level
> 0 ?
460 aux_param
.suffix
[0] : cur
->high
; k
> 9; k
/= 10)
464 if (cur
->hidden_level
&& hidden_level
== 0) {
466 for (k
= aux_param
.hidden_level
>= 0 ?
467 aux_param
.hidden_level
: cur
->hidden_high
; k
> 9; k
/= 10)
471 len
= strlen(cur
->name
) + j
;
472 i
= low
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->low
;
475 db_printf(cur
->name
);
476 j
= strlen(cur
->name
);
477 if (cur
->high
>= 0) {
478 if (cur
->min_level
> 0) {
481 for (k
= i
; k
> 9; k
/= 10)
484 if (cur
->hidden_level
&& hidden_level
== 0) {
486 for (k
= i
; k
> 9; k
/= 10)
488 while (sl
++ < slen
) {
492 db_printf("[%d]", h
);
494 for (k
= h
; k
> 9; k
/= 10)
505 aux_param
.suffix
[0] = i
;
506 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
508 db_printf("%#lln", (unsigned long long)*(cur
->valuep
+ i
));
509 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
511 if (name
!= (char *)0 && offset
<= db_maxoff
&&
512 offset
!= *(cur
->valuep
+ i
)) {
513 db_printf("\t%s", name
);
515 db_printf("+%#llr", (unsigned long long)offset
);
521 if (aux_param
.level
> 0 || i
++ == cur
->high
) {
522 if (!cur
->hidden_level
||
524 h
++ == cur
->hidden_high
)
526 aux_param
.hidden_level
= h
;
533 db_show_variable(void)
535 struct db_variable
*cur
;
546 struct db_var_aux_param aux_param
;
550 switch(t
= db_read_token()) {
557 t1
= db_read_token();
559 db_show_one_variable();
562 db_error("Not a variable name after $\n");
567 db_error("Variable name should be prefixed with $\n");
574 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
575 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
578 if (cur
->min_level
> 0) {
580 for (k
= cur
->high
; k
> 9; k
/= 10)
584 if (cur
->hidden_level
&&
585 (*cur
->hidden_levelp
< cur
->hidden_low
||
586 *cur
->hidden_levelp
> cur
->hidden_high
)) {
588 for (k
= cur
->hidden_high
; k
> 9; k
/= 10)
592 if ((l
= strlen(cur
->name
) + j
) >= len
)
596 aux_param
.modif
= "";
598 aux_param
.thr_act
= THREAD_NULL
;
600 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
602 if (cur
->hidden_level
) {
603 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
604 *cur
->hidden_levelp
<= cur
->hidden_high
) {
605 h
= cur
->hidden_low
- 1;
606 aux_param
.hidden_level
= *cur
->hidden_levelp
;
609 aux_param
.hidden_level
= cur
->hidden_low
;
612 for (k
= cur
->high
; k
> 9; k
/= 10)
615 aux_param
.hidden_level
= -1;
617 if (cur
!= db_vars
&& cur
->high
>= 0 &&
618 (cur
->min_level
> 0 || cur
->hidden_level
))
622 db_printf(cur
->name
);
623 j
= strlen(cur
->name
);
624 if (cur
->high
>= 0) {
625 if (cur
->min_level
> 0) {
628 for (k
= i
; k
> 9; k
/= 10)
631 if (cur
->hidden_level
&& h
>= cur
->hidden_low
) {
633 for (k
= i
; k
> 9; k
/= 10)
635 while (sl
++ < slen
) {
639 db_printf("[%d]", h
);
641 for (k
= h
; k
> 9; k
/= 10)
651 aux_param
.suffix
[0] = i
;
652 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
654 db_printf("%#lln", (unsigned long long)*(cur
->valuep
+ i
));
655 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
657 if (name
!= (char *)0 && offset
<= db_maxoff
&&
658 offset
!= *(cur
->valuep
+ i
)) {
659 db_printf("\t%s", name
);
661 db_printf("+%#llr", (unsigned long long)offset
);
667 if (i
++ == cur
->high
) {
668 if (!cur
->hidden_level
|| h
++ == cur
->hidden_high
)
670 aux_param
.hidden_level
= h
;
678 * given a name of a machine register, return a variable pointer to it.
684 register db_variable_t regp
;
686 if ( s
== (char *)0 )
689 for (regp
= db_regs
; regp
< db_eregs
; regp
++) {
690 if ( strcmp( s
, regp
->name
) == 0 )