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@
31 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
32 * Import of Mac OS X kernel (~semeria)
34 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
35 * Import of OSF Mach kernel (~mburg)
37 * Revision 1.2.18.5 1996/01/09 19:16:34 devrcs
38 * Search the alternate register names if configured
39 * Changed declarations of 'register foo' to 'register int foo'.
40 * [1995/12/01 21:42:42 jfraser]
42 * Merged '64-bit safe' changes from DEC alpha port.
43 * [1995/11/21 18:03:56 jfraser]
45 * Revision 1.2.18.4 1995/02/23 21:43:56 alanl
46 * Merged with DIPC2_SHARED.
47 * [1995/01/05 13:35:55 alanl]
49 * Revision 1.2.21.1 1994/11/04 09:53:26 dwm
50 * mk6 CR668 - 1.3b26 merge
51 * * Revision 1.2.4.6 1994/05/06 18:40:13 tmt
52 * Merged osc1.3dec/shared with osc1.3b19
53 * Merge Alpha changes into osc1.312b source code.
56 * [1994/11/04 08:50:12 dwm]
58 * Revision 1.2.18.2 1994/09/23 01:22:35 ezf
59 * change marker to not FREE
60 * [1994/09/22 21:11:24 ezf]
62 * Revision 1.2.18.1 1994/06/11 21:12:37 bolinger
63 * Merge up to NMK17.2.
64 * [1994/06/11 20:03:04 bolinger]
66 * Revision 1.2.23.1 1994/12/06 19:43:18 alanl
67 * Intel merge, Oct 94 code drop.
68 * Added db_find_reg_name (came from db_print.c).
71 * Revision 1.2.16.1 1994/02/08 10:59:08 bernadat
72 * Added completion variable.
75 * Set up new fields (hidden_xxx) of db_vars[] array that are supposed
76 * to be helpful to display variables depending on an internal value
77 * like db_macro_level for macro arguments.
78 * Added db_auto_wrap as new variable.
79 * Added "set help" for listing all available variables.
80 * Added db_show_variable() and db_show_one_variable()
81 * to print variable values.
85 * Revision 1.2.4.4 1993/08/11 20:38:20 elliston
86 * Add ANSI Prototypes. CR #9523.
87 * [1993/08/11 03:34:13 elliston]
89 * Revision 1.2.4.3 1993/07/27 18:28:27 elliston
90 * Add ANSI prototypes. CR #9523.
91 * [1993/07/27 18:13:22 elliston]
93 * Revision 1.2.4.2 1993/06/09 02:21:02 gm
94 * Added to OSF/1 R1.3 from NMK15.0.
95 * [1993/06/02 20:57:43 jeffc]
97 * Revision 1.2 1993/04/19 16:03:25 devrcs
99 * Added void to db_read_write_variable().
100 * Removed unused variable 'func' from db_set_cmd().
104 * Print old value when changing register values.
105 * [barbou@gr.osf.org]
106 * [92/12/03 bernadat]
108 * Revision 1.1 1992/09/30 02:01:31 robert
115 * Revision 2.5 91/10/09 16:03:59 af
116 * Revision 2.4.3.1 91/10/05 13:08:27 jeffreyh
117 * Added suffix handling and thread handling of variables.
118 * Added new variables: lines, task, thread, work and arg.
119 * Moved db_read_variable and db_write_variable to db_variables.h
120 * as macros, and added db_read_write_variable instead.
121 * Changed some error messages.
124 * Revision 2.4.3.1 91/10/05 13:08:27 jeffreyh
125 * Added suffix handling and thread handling of variables.
126 * Added new variables: lines, task, thread, work and arg.
127 * Moved db_read_variable and db_write_variable to db_variables.h
128 * as macros, and added db_read_write_variable instead.
129 * Changed some error messages.
132 * Revision 2.4 91/05/14 15:36:57 mrt
133 * Correcting copyright
135 * Revision 2.3 91/02/05 17:07:19 mrt
136 * Changed to new Mach copyright
137 * [91/01/31 16:19:46 mrt]
139 * Revision 2.2 90/08/27 21:53:24 dbg
140 * New db_read/write_variable functions. Should be used instead
141 * of dereferencing valuep directly, which might not be a true
142 * pointer if there is an fcn() access function.
146 * Check for trailing garbage after last expression on command line.
147 * [90/08/10 14:34:54 dbg]
155 * Mach Operating System
156 * Copyright (c) 1991,1990 Carnegie Mellon University
157 * All Rights Reserved.
159 * Permission to use, copy, modify and distribute this software and its
160 * documentation is hereby granted, provided that both the copyright
161 * notice and this permission notice appear in all copies of the
162 * software, derivative works or modified versions, and any portions
163 * thereof, and that both notices appear in supporting documentation.
165 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
166 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
167 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
169 * Carnegie Mellon requests users of this software to return to
171 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
172 * School of Computer Science
173 * Carnegie Mellon University
174 * Pittsburgh PA 15213-3890
176 * any improvements or extensions that they make and grant Carnegie Mellon
177 * the rights to redistribute these changes.
182 * Author: David B. Golub, Carnegie Mellon University
186 #include <machine/db_machdep.h>
187 #include <string.h> /* For strcpy() */
189 #include <ddb/db_lex.h>
190 #include <ddb/db_variables.h>
191 #include <ddb/db_task_thread.h>
192 #include <ddb/db_sym.h>
193 #include <ddb/db_command.h>
194 #include <ddb/db_expr.h>
195 #include <ddb/db_macro.h>
196 #include <ddb/db_output.h> /* For db_printf() */
198 extern db_expr_t db_radix
;
199 extern db_expr_t db_max_width
;
200 extern db_expr_t db_tab_stop_width
;
201 extern db_expr_t db_max_line
;
202 extern db_expr_t db_auto_wrap
;
203 extern db_expr_t db_macro_level
;
204 extern db_expr_t db_auto_completion
;
206 #define DB_NWORK 32 /* number of work variable */
208 db_expr_t db_work
[DB_NWORK
]; /* work variable */
210 struct db_variable db_vars
[] = {
211 { "maxoff", (db_expr_t
*)&db_maxoff
, FCN_NULL
},
212 { "autowrap", &db_auto_wrap
, FCN_NULL
},
213 { "completion", &db_auto_completion
, FCN_NULL
},
214 { "maxwidth", &db_max_width
, FCN_NULL
},
215 { "radix", &db_radix
, FCN_NULL
},
216 { "tabstops", &db_tab_stop_width
, FCN_NULL
},
217 { "lines", &db_max_line
, FCN_NULL
},
218 { "thr_act", 0, db_set_default_act
},
219 { "task", 0, db_get_task_act
,
221 { "work", &db_work
[0], FCN_NULL
,
222 1, 1, 0, DB_NWORK
-1 },
223 { "arg", 0, db_arg_variable
,
224 1, 1, 1, DB_MACRO_NARGS
,
225 1, 0, DB_MACRO_LEVEL
-1, (int *)&db_macro_level
},
227 struct db_variable
*db_evars
= db_vars
+ sizeof(db_vars
)/sizeof(db_vars
[0]);
231 /* Prototypes for functions local to this file.
234 static char *db_get_suffix(
235 register char *suffix
,
236 short *suffix_value
);
238 static boolean_t
db_cmp_variable_name(
239 struct db_variable
*vp
,
241 register db_var_aux_param_t ap
);
243 static int db_find_variable(
244 struct db_variable
**varp
,
245 db_var_aux_param_t ap
);
247 static int db_set_variable(db_expr_t value
);
249 void db_list_variable(void);
253 register char *suffix
,
258 for (value
= 0; *suffix
&& *suffix
!= '.' && *suffix
!= ':'; suffix
++) {
259 if (*suffix
< '0' || *suffix
> '9')
261 value
= value
*10 + *suffix
- '0';
263 *suffix_value
= value
;
270 db_cmp_variable_name(
271 struct db_variable
*vp
,
273 register db_var_aux_param_t ap
)
275 register char *var_np
, *np
;
278 for (np
= name
, var_np
= vp
->name
; *var_np
; ) {
279 if (*np
++ != *var_np
++)
282 for (level
= 0; *np
&& *np
!= ':' && level
< vp
->max_level
; level
++){
283 if ((np
= db_get_suffix(np
, &ap
->suffix
[level
])) == 0)
286 if ((*np
&& *np
!= ':') || level
< vp
->min_level
287 || (level
> 0 && (ap
->suffix
[0] < vp
->low
288 || (vp
->high
>= 0 && ap
->suffix
[0] > vp
->high
))))
290 strcpy(ap
->modif
, (*np
)? np
+1: "");
291 ap
->thr_act
= (db_option(ap
->modif
, 't')?db_default_act
: THR_ACT_NULL
);
293 ap
->hidden_level
= -1;
299 struct db_variable
**varp
,
300 db_var_aux_param_t ap
)
303 struct db_variable
*vp
;
307 for (vp
= db_vars
; vp
< db_evars
; vp
++) {
308 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
313 for (vp
= db_regs
; vp
< db_eregs
; vp
++) {
314 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
319 #if defined(ALTERNATE_REGISTER_DEFS)
320 for (vp
= db_altregs
; vp
< db_ealtregs
; vp
++) {
321 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
326 #endif /* defined(ALTERNATE_REGISTER_DEFS) */
328 db_printf("Unknown variable \"$%s\"\n", db_tok_string
);
334 db_get_variable(db_expr_t
*valuep
)
336 struct db_variable
*vp
;
337 struct db_var_aux_param aux_param
;
338 char modif
[TOK_STRING_SIZE
];
340 aux_param
.modif
= modif
;
341 if (!db_find_variable(&vp
, &aux_param
))
344 db_read_write_variable(vp
, valuep
, DB_VAR_GET
, &aux_param
);
350 db_set_variable(db_expr_t value
)
352 struct db_variable
*vp
;
353 struct db_var_aux_param aux_param
;
354 char modif
[TOK_STRING_SIZE
];
356 aux_param
.modif
= modif
;
357 if (!db_find_variable(&vp
, &aux_param
))
360 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
366 db_read_write_variable(
367 struct db_variable
*vp
,
370 db_var_aux_param_t ap
)
372 int (*func
)(struct db_variable
*, db_expr_t
*,int, db_var_aux_param_t
)
374 struct db_var_aux_param aux_param
;
381 ap
->thr_act
= THR_ACT_NULL
;
383 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
384 db_read_write_variable(vp
, &old_value
, DB_VAR_GET
, ap
);
385 if (func
== FCN_NULL
) {
386 if (rw_flag
== DB_VAR_SET
)
387 vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0] = *valuep
;
389 *valuep
= vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0];
391 (*func
)(vp
, valuep
, rw_flag
, ap
);
392 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
393 db_printf("\t$%s:%s<%#x>\t%#8n\t=\t%#8n\n", vp
->name
,
394 ap
->modif
, ap
->thr_act
, old_value
, *valuep
);
398 db_list_variable(void)
400 register struct db_variable
*new;
401 register struct db_variable
*old
;
402 register struct db_variable
*cur
;
409 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
410 if (cur
->min_level
> 0 || cur
->max_level
> 0) {
411 j
= 3 * (cur
->max_level
- cur
->min_level
+ 1) - 1;
412 if (cur
->max_level
> cur
->min_level
)
416 if ((l
= strlen(cur
->name
) + j
) >= len
)
420 old
= (struct db_variable
*)0;
422 new = (struct db_variable
*)0;
423 for (cur
= db_vars
; cur
< db_evars
; cur
++)
424 if ((new == (struct db_variable
*)0 ||
425 strcmp(cur
->name
, new->name
) < 0) &&
426 (old
== (struct db_variable
*)0 ||
427 strcmp(cur
->name
, old
->name
) > 0))
429 if (new == (struct db_variable
*)0)
431 db_reserve_output_position(len
);
432 db_printf(new->name
);
433 j
= strlen(new->name
);
434 if (new->min_level
> 0) {
438 for (i
= new->min_level
- 1; i
> 0; i
--) {
444 if (new->max_level
> new->min_level
) {
451 i
= new->min_level
+ 1;
453 if (new->max_level
> new->min_level
) {
459 while (i
++ < new->max_level
) {
465 if (new->max_level
> new->min_level
) {
480 struct db_variable
*vp
;
481 struct db_var_aux_param aux_param
;
482 char modif
[TOK_STRING_SIZE
];
484 aux_param
.modif
= modif
;
486 if (t
== tIDENT
&& strcmp("help", db_tok_string
) == 0) {
491 db_error("Variable name should be prefixed with $\n");
494 if (!db_find_variable(&vp
, &aux_param
)) {
495 db_error("Unknown variable\n");
503 if (!db_expression(&value
)) {
504 db_error("No value\n");
507 if ((t
= db_read_token()) == tSEMI_COLON
)
512 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
516 db_show_one_variable(void)
518 struct db_variable
*cur
;
528 struct db_var_aux_param aux_param
;
534 for (cur
= db_vars
; cur
< db_evars
; cur
++)
535 if (db_cmp_variable_name(cur
, db_tok_string
, &aux_param
))
537 if (cur
== db_evars
) {
538 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
539 for (q
= cur
->name
, p
= db_tok_string
; *q
&& *p
== *q
; p
++,q
++)
544 if (cur
== db_evars
) {
545 db_error("Unknown variable\n");
549 for (i
= 0; *p
&& *p
!= ':' && i
< cur
->max_level
; i
++, p
= q
)
550 if ((q
= db_get_suffix(p
, &aux_param
.suffix
[i
])) == 0)
553 if ((*p
&& *p
!= ':') ||
554 (i
> 0 && (aux_param
.suffix
[0] < cur
->low
||
556 aux_param
.suffix
[0] > cur
->high
)))) {
557 db_error("Unknown variable format\n");
561 strcpy(aux_param
.modif
, *p
? p
+ 1 : "");
562 aux_param
.thr_act
= (db_option(aux_param
.modif
, 't') ?
563 db_default_act
: THR_ACT_NULL
);
566 if (cur
->hidden_level
)
567 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
568 *cur
->hidden_levelp
<= cur
->hidden_high
) {
570 aux_param
.hidden_level
= h
= *cur
->hidden_levelp
;
573 aux_param
.hidden_level
= h
= cur
->hidden_low
;
575 for (k
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->high
;
580 aux_param
.hidden_level
= -1;
582 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
585 if (cur
->min_level
> 0) {
587 for (k
= aux_param
.level
> 0 ?
588 aux_param
.suffix
[0] : cur
->high
; k
> 9; k
/= 10)
592 if (cur
->hidden_level
&& hidden_level
== 0) {
594 for (k
= aux_param
.hidden_level
>= 0 ?
595 aux_param
.hidden_level
: cur
->hidden_high
; k
> 9; k
/= 10)
599 len
= strlen(cur
->name
) + j
;
600 i
= low
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->low
;
603 db_printf(cur
->name
);
604 j
= strlen(cur
->name
);
605 if (cur
->high
>= 0) {
606 if (cur
->min_level
> 0) {
609 for (k
= i
; k
> 9; k
/= 10)
612 if (cur
->hidden_level
&& hidden_level
== 0) {
614 for (k
= i
; k
> 9; k
/= 10)
616 while (sl
++ < slen
) {
620 db_printf("[%d]", h
);
622 for (k
= h
; k
> 9; k
/= 10)
633 aux_param
.suffix
[0] = i
;
634 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
636 db_printf("%#n", *(cur
->valuep
+ i
));
637 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
639 if (name
!= (char *)0 && offset
<= db_maxoff
&&
640 offset
!= *(cur
->valuep
+ i
)) {
641 db_printf("\t%s", name
);
643 db_printf("+%#r", offset
);
649 if (aux_param
.level
> 0 || i
++ == cur
->high
) {
650 if (!cur
->hidden_level
||
652 h
++ == cur
->hidden_high
)
654 aux_param
.hidden_level
= h
;
661 db_show_variable(void)
663 struct db_variable
*cur
;
674 struct db_var_aux_param aux_param
;
678 switch(t
= db_read_token()) {
685 t1
= db_read_token();
687 db_show_one_variable();
690 db_error("Not a variable name after $\n");
695 db_error("Variable name should be prefixed with $\n");
702 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
703 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
706 if (cur
->min_level
> 0) {
708 for (k
= cur
->high
; k
> 9; k
/= 10)
712 if (cur
->hidden_level
&&
713 (*cur
->hidden_levelp
< cur
->hidden_low
||
714 *cur
->hidden_levelp
> cur
->hidden_high
)) {
716 for (k
= cur
->hidden_high
; k
> 9; k
/= 10)
720 if ((l
= strlen(cur
->name
) + j
) >= len
)
724 aux_param
.modif
= "";
726 aux_param
.thr_act
= THR_ACT_NULL
;
728 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
730 if (cur
->hidden_level
) {
731 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
732 *cur
->hidden_levelp
<= cur
->hidden_high
) {
733 h
= cur
->hidden_low
- 1;
734 aux_param
.hidden_level
= *cur
->hidden_levelp
;
737 aux_param
.hidden_level
= cur
->hidden_low
;
740 for (k
= cur
->high
; k
> 9; k
/= 10)
743 aux_param
.hidden_level
= -1;
745 if (cur
!= db_vars
&& cur
->high
>= 0 &&
746 (cur
->min_level
> 0 || cur
->hidden_level
))
750 db_printf(cur
->name
);
751 j
= strlen(cur
->name
);
752 if (cur
->high
>= 0) {
753 if (cur
->min_level
> 0) {
756 for (k
= i
; k
> 9; k
/= 10)
759 if (cur
->hidden_level
&& h
>= cur
->hidden_low
) {
761 for (k
= i
; k
> 9; k
/= 10)
763 while (sl
++ < slen
) {
767 db_printf("[%d]", h
);
769 for (k
= h
; k
> 9; k
/= 10)
779 aux_param
.suffix
[0] = i
;
780 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
782 db_printf("%#n", *(cur
->valuep
+ i
));
783 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
785 if (name
!= (char *)0 && offset
<= db_maxoff
&&
786 offset
!= *(cur
->valuep
+ i
)) {
787 db_printf("\t%s", name
);
789 db_printf("+%#r", offset
);
795 if (i
++ == cur
->high
) {
796 if (!cur
->hidden_level
|| h
++ == cur
->hidden_high
)
798 aux_param
.hidden_level
= h
;
806 * given a name of a machine register, return a variable pointer to it.
812 register db_variable_t regp
;
814 if ( s
== (char *)0 )
817 for (regp
= db_regs
; regp
< db_eregs
; regp
++) {
818 if ( strcmp( s
, regp
->name
) == 0 )