2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
29 * Mach Operating System
30 * Copyright (c) 1991,1990 Carnegie Mellon University
31 * All Rights Reserved.
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 * Carnegie Mellon requests users of this software to return to
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
50 * any improvements or extensions that they make and grant Carnegie Mellon
51 * the rights to redistribute these changes.
56 * Author: David B. Golub, Carnegie Mellon University
60 #include <machine/db_machdep.h>
61 #include <string.h> /* For strcpy() */
63 #include <ddb/db_lex.h>
64 #include <ddb/db_variables.h>
65 #include <ddb/db_task_thread.h>
66 #include <ddb/db_sym.h>
67 #include <ddb/db_command.h>
68 #include <ddb/db_expr.h>
69 #include <ddb/db_macro.h>
70 #include <ddb/db_output.h> /* For db_printf() */
72 extern db_expr_t db_radix
;
73 extern db_expr_t db_max_width
;
74 extern db_expr_t db_tab_stop_width
;
75 extern db_expr_t db_max_line
;
76 extern db_expr_t db_auto_wrap
;
77 extern db_expr_t db_macro_level
;
78 extern db_expr_t db_auto_completion
;
80 #define DB_NWORK 32 /* number of work variable */
82 db_expr_t db_work
[DB_NWORK
]; /* work variable */
84 struct db_variable db_vars
[] = {
85 { "maxoff", (db_expr_t
*)&db_maxoff
, FCN_NULL
},
86 { "autowrap", &db_auto_wrap
, FCN_NULL
},
87 { "completion", &db_auto_completion
, FCN_NULL
},
88 { "maxwidth", &db_max_width
, FCN_NULL
},
89 { "radix", &db_radix
, FCN_NULL
},
90 { "tabstops", &db_tab_stop_width
, FCN_NULL
},
91 { "lines", &db_max_line
, FCN_NULL
},
92 { "thr_act", 0, db_set_default_act
},
93 { "task", 0, db_get_task_act
,
95 { "work", &db_work
[0], FCN_NULL
,
96 1, 1, 0, DB_NWORK
-1 },
97 { "arg", 0, db_arg_variable
,
98 1, 1, 1, DB_MACRO_NARGS
,
99 1, 0, DB_MACRO_LEVEL
-1, (int *)&db_macro_level
},
101 struct db_variable
*db_evars
= db_vars
+ sizeof(db_vars
)/sizeof(db_vars
[0]);
105 /* Prototypes for functions local to this file.
108 static char *db_get_suffix(
109 register char *suffix
,
110 short *suffix_value
);
112 static boolean_t
db_cmp_variable_name(
113 struct db_variable
*vp
,
115 register db_var_aux_param_t ap
);
117 static int db_find_variable(
118 struct db_variable
**varp
,
119 db_var_aux_param_t ap
);
121 static int db_set_variable(db_expr_t value
);
123 void db_list_variable(void);
127 register char *suffix
,
132 for (value
= 0; *suffix
&& *suffix
!= '.' && *suffix
!= ':'; suffix
++) {
133 if (*suffix
< '0' || *suffix
> '9')
135 value
= value
*10 + *suffix
- '0';
137 *suffix_value
= value
;
144 db_cmp_variable_name(
145 struct db_variable
*vp
,
147 register db_var_aux_param_t ap
)
149 register char *var_np
, *np
;
152 for (np
= name
, var_np
= vp
->name
; *var_np
; ) {
153 if (*np
++ != *var_np
++)
156 for (level
= 0; *np
&& *np
!= ':' && level
< vp
->max_level
; level
++){
157 if ((np
= db_get_suffix(np
, &ap
->suffix
[level
])) == 0)
160 if ((*np
&& *np
!= ':') || level
< vp
->min_level
161 || (level
> 0 && (ap
->suffix
[0] < vp
->low
162 || (vp
->high
>= 0 && ap
->suffix
[0] > vp
->high
))))
164 strcpy(ap
->modif
, (*np
)? np
+1: "");
165 ap
->thr_act
= (db_option(ap
->modif
, 't')?db_default_act
: THR_ACT_NULL
);
167 ap
->hidden_level
= -1;
173 struct db_variable
**varp
,
174 db_var_aux_param_t ap
)
177 struct db_variable
*vp
;
181 for (vp
= db_vars
; vp
< db_evars
; vp
++) {
182 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
187 for (vp
= db_regs
; vp
< db_eregs
; vp
++) {
188 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
193 #if defined(ALTERNATE_REGISTER_DEFS)
194 for (vp
= db_altregs
; vp
< db_ealtregs
; vp
++) {
195 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
200 #endif /* defined(ALTERNATE_REGISTER_DEFS) */
202 db_printf("Unknown variable \"$%s\"\n", db_tok_string
);
208 db_get_variable(db_expr_t
*valuep
)
210 struct db_variable
*vp
;
211 struct db_var_aux_param aux_param
;
212 char modif
[TOK_STRING_SIZE
];
214 aux_param
.modif
= modif
;
215 if (!db_find_variable(&vp
, &aux_param
))
218 db_read_write_variable(vp
, valuep
, DB_VAR_GET
, &aux_param
);
224 db_set_variable(db_expr_t value
)
226 struct db_variable
*vp
;
227 struct db_var_aux_param aux_param
;
228 char modif
[TOK_STRING_SIZE
];
230 aux_param
.modif
= modif
;
231 if (!db_find_variable(&vp
, &aux_param
))
234 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
240 db_read_write_variable(
241 struct db_variable
*vp
,
244 db_var_aux_param_t ap
)
246 int (*func
)(struct db_variable
*, db_expr_t
*,int, db_var_aux_param_t
)
248 struct db_var_aux_param aux_param
;
255 ap
->thr_act
= THR_ACT_NULL
;
257 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
258 db_read_write_variable(vp
, &old_value
, DB_VAR_GET
, ap
);
259 if (func
== FCN_NULL
) {
260 if (rw_flag
== DB_VAR_SET
)
261 vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0] = *valuep
;
263 *valuep
= vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0];
265 (*func
)(vp
, valuep
, rw_flag
, ap
);
266 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
267 db_printf("\t$%s:%s<%#x>\t%#8lln\t=\t%#8lln\n", vp
->name
,
268 ap
->modif
, ap
->thr_act
, old_value
, *valuep
);
272 db_list_variable(void)
274 register struct db_variable
*new;
275 register struct db_variable
*old
;
276 register struct db_variable
*cur
;
283 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
284 if (cur
->min_level
> 0 || cur
->max_level
> 0) {
285 j
= 3 * (cur
->max_level
- cur
->min_level
+ 1) - 1;
286 if (cur
->max_level
> cur
->min_level
)
290 if ((l
= strlen(cur
->name
) + j
) >= len
)
294 old
= (struct db_variable
*)0;
296 new = (struct db_variable
*)0;
297 for (cur
= db_vars
; cur
< db_evars
; cur
++)
298 if ((new == (struct db_variable
*)0 ||
299 strcmp(cur
->name
, new->name
) < 0) &&
300 (old
== (struct db_variable
*)0 ||
301 strcmp(cur
->name
, old
->name
) > 0))
303 if (new == (struct db_variable
*)0)
305 db_reserve_output_position(len
);
306 db_printf(new->name
);
307 j
= strlen(new->name
);
308 if (new->min_level
> 0) {
312 for (i
= new->min_level
- 1; i
> 0; i
--) {
318 if (new->max_level
> new->min_level
) {
325 i
= new->min_level
+ 1;
327 if (new->max_level
> new->min_level
) {
333 while (i
++ < new->max_level
) {
339 if (new->max_level
> new->min_level
) {
354 struct db_variable
*vp
;
355 struct db_var_aux_param aux_param
;
356 char modif
[TOK_STRING_SIZE
];
358 aux_param
.modif
= modif
;
360 if (t
== tIDENT
&& strcmp("help", db_tok_string
) == 0) {
365 db_error("Variable name should be prefixed with $\n");
368 if (!db_find_variable(&vp
, &aux_param
)) {
369 db_error("Unknown variable\n");
377 if (!db_expression(&value
)) {
378 db_error("No value\n");
381 if ((t
= db_read_token()) == tSEMI_COLON
)
386 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
390 db_show_one_variable(void)
392 struct db_variable
*cur
;
402 struct db_var_aux_param aux_param
;
408 for (cur
= db_vars
; cur
< db_evars
; cur
++)
409 if (db_cmp_variable_name(cur
, db_tok_string
, &aux_param
))
411 if (cur
== db_evars
) {
412 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
413 for (q
= cur
->name
, p
= db_tok_string
; *q
&& *p
== *q
; p
++,q
++)
418 if (cur
== db_evars
) {
419 db_error("Unknown variable\n");
423 for (i
= 0; *p
&& *p
!= ':' && i
< cur
->max_level
; i
++, p
= q
)
424 if ((q
= db_get_suffix(p
, &aux_param
.suffix
[i
])) == 0)
427 if ((*p
&& *p
!= ':') ||
428 (i
> 0 && (aux_param
.suffix
[0] < cur
->low
||
430 aux_param
.suffix
[0] > cur
->high
)))) {
431 db_error("Unknown variable format\n");
435 strcpy(aux_param
.modif
, *p
? p
+ 1 : "");
436 aux_param
.thr_act
= (db_option(aux_param
.modif
, 't') ?
437 db_default_act
: THR_ACT_NULL
);
440 if (cur
->hidden_level
)
441 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
442 *cur
->hidden_levelp
<= cur
->hidden_high
) {
444 aux_param
.hidden_level
= h
= *cur
->hidden_levelp
;
447 aux_param
.hidden_level
= h
= cur
->hidden_low
;
449 for (k
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->high
;
454 aux_param
.hidden_level
= -1;
456 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
459 if (cur
->min_level
> 0) {
461 for (k
= aux_param
.level
> 0 ?
462 aux_param
.suffix
[0] : cur
->high
; k
> 9; k
/= 10)
466 if (cur
->hidden_level
&& hidden_level
== 0) {
468 for (k
= aux_param
.hidden_level
>= 0 ?
469 aux_param
.hidden_level
: cur
->hidden_high
; k
> 9; k
/= 10)
473 len
= strlen(cur
->name
) + j
;
474 i
= low
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->low
;
477 db_printf(cur
->name
);
478 j
= strlen(cur
->name
);
479 if (cur
->high
>= 0) {
480 if (cur
->min_level
> 0) {
483 for (k
= i
; k
> 9; k
/= 10)
486 if (cur
->hidden_level
&& hidden_level
== 0) {
488 for (k
= i
; k
> 9; k
/= 10)
490 while (sl
++ < slen
) {
494 db_printf("[%d]", h
);
496 for (k
= h
; k
> 9; k
/= 10)
507 aux_param
.suffix
[0] = i
;
508 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
510 db_printf("%#lln", *(cur
->valuep
+ i
));
511 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
513 if (name
!= (char *)0 && offset
<= db_maxoff
&&
514 offset
!= *(cur
->valuep
+ i
)) {
515 db_printf("\t%s", name
);
517 db_printf("+%#r", offset
);
523 if (aux_param
.level
> 0 || i
++ == cur
->high
) {
524 if (!cur
->hidden_level
||
526 h
++ == cur
->hidden_high
)
528 aux_param
.hidden_level
= h
;
535 db_show_variable(void)
537 struct db_variable
*cur
;
548 struct db_var_aux_param aux_param
;
552 switch(t
= db_read_token()) {
559 t1
= db_read_token();
561 db_show_one_variable();
564 db_error("Not a variable name after $\n");
569 db_error("Variable name should be prefixed with $\n");
576 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
577 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
580 if (cur
->min_level
> 0) {
582 for (k
= cur
->high
; k
> 9; k
/= 10)
586 if (cur
->hidden_level
&&
587 (*cur
->hidden_levelp
< cur
->hidden_low
||
588 *cur
->hidden_levelp
> cur
->hidden_high
)) {
590 for (k
= cur
->hidden_high
; k
> 9; k
/= 10)
594 if ((l
= strlen(cur
->name
) + j
) >= len
)
598 aux_param
.modif
= "";
600 aux_param
.thr_act
= THR_ACT_NULL
;
602 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
604 if (cur
->hidden_level
) {
605 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
606 *cur
->hidden_levelp
<= cur
->hidden_high
) {
607 h
= cur
->hidden_low
- 1;
608 aux_param
.hidden_level
= *cur
->hidden_levelp
;
611 aux_param
.hidden_level
= cur
->hidden_low
;
614 for (k
= cur
->high
; k
> 9; k
/= 10)
617 aux_param
.hidden_level
= -1;
619 if (cur
!= db_vars
&& cur
->high
>= 0 &&
620 (cur
->min_level
> 0 || cur
->hidden_level
))
624 db_printf(cur
->name
);
625 j
= strlen(cur
->name
);
626 if (cur
->high
>= 0) {
627 if (cur
->min_level
> 0) {
630 for (k
= i
; k
> 9; k
/= 10)
633 if (cur
->hidden_level
&& h
>= cur
->hidden_low
) {
635 for (k
= i
; k
> 9; k
/= 10)
637 while (sl
++ < slen
) {
641 db_printf("[%d]", h
);
643 for (k
= h
; k
> 9; k
/= 10)
653 aux_param
.suffix
[0] = i
;
654 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
656 db_printf("%#lln", *(cur
->valuep
+ i
));
657 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
659 if (name
!= (char *)0 && offset
<= db_maxoff
&&
660 offset
!= *(cur
->valuep
+ i
)) {
661 db_printf("\t%s", name
);
663 db_printf("+%#r", offset
);
669 if (i
++ == cur
->high
) {
670 if (!cur
->hidden_level
|| h
++ == cur
->hidden_high
)
672 aux_param
.hidden_level
= h
;
680 * given a name of a machine register, return a variable pointer to it.
686 register db_variable_t regp
;
688 if ( s
== (char *)0 )
691 for (regp
= db_regs
; regp
< db_eregs
; regp
++) {
692 if ( strcmp( s
, regp
->name
) == 0 )