2 * Copyright (c) 2000 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@
28 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
29 * Import of Mac OS X kernel (~semeria)
31 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
32 * Import of OSF Mach kernel (~mburg)
34 * Revision 1.2.18.5 1996/01/09 19:16:34 devrcs
35 * Search the alternate register names if configured
36 * Changed declarations of 'register foo' to 'register int foo'.
37 * [1995/12/01 21:42:42 jfraser]
39 * Merged '64-bit safe' changes from DEC alpha port.
40 * [1995/11/21 18:03:56 jfraser]
42 * Revision 1.2.18.4 1995/02/23 21:43:56 alanl
43 * Merged with DIPC2_SHARED.
44 * [1995/01/05 13:35:55 alanl]
46 * Revision 1.2.21.1 1994/11/04 09:53:26 dwm
47 * mk6 CR668 - 1.3b26 merge
48 * * Revision 1.2.4.6 1994/05/06 18:40:13 tmt
49 * Merged osc1.3dec/shared with osc1.3b19
50 * Merge Alpha changes into osc1.312b source code.
53 * [1994/11/04 08:50:12 dwm]
55 * Revision 1.2.18.2 1994/09/23 01:22:35 ezf
56 * change marker to not FREE
57 * [1994/09/22 21:11:24 ezf]
59 * Revision 1.2.18.1 1994/06/11 21:12:37 bolinger
60 * Merge up to NMK17.2.
61 * [1994/06/11 20:03:04 bolinger]
63 * Revision 1.2.23.1 1994/12/06 19:43:18 alanl
64 * Intel merge, Oct 94 code drop.
65 * Added db_find_reg_name (came from db_print.c).
68 * Revision 1.2.16.1 1994/02/08 10:59:08 bernadat
69 * Added completion variable.
72 * Set up new fields (hidden_xxx) of db_vars[] array that are supposed
73 * to be helpful to display variables depending on an internal value
74 * like db_macro_level for macro arguments.
75 * Added db_auto_wrap as new variable.
76 * Added "set help" for listing all available variables.
77 * Added db_show_variable() and db_show_one_variable()
78 * to print variable values.
82 * Revision 1.2.4.4 1993/08/11 20:38:20 elliston
83 * Add ANSI Prototypes. CR #9523.
84 * [1993/08/11 03:34:13 elliston]
86 * Revision 1.2.4.3 1993/07/27 18:28:27 elliston
87 * Add ANSI prototypes. CR #9523.
88 * [1993/07/27 18:13:22 elliston]
90 * Revision 1.2.4.2 1993/06/09 02:21:02 gm
91 * Added to OSF/1 R1.3 from NMK15.0.
92 * [1993/06/02 20:57:43 jeffc]
94 * Revision 1.2 1993/04/19 16:03:25 devrcs
96 * Added void to db_read_write_variable().
97 * Removed unused variable 'func' from db_set_cmd().
101 * Print old value when changing register values.
102 * [barbou@gr.osf.org]
103 * [92/12/03 bernadat]
105 * Revision 1.1 1992/09/30 02:01:31 robert
112 * Revision 2.5 91/10/09 16:03:59 af
113 * Revision 2.4.3.1 91/10/05 13:08:27 jeffreyh
114 * Added suffix handling and thread handling of variables.
115 * Added new variables: lines, task, thread, work and arg.
116 * Moved db_read_variable and db_write_variable to db_variables.h
117 * as macros, and added db_read_write_variable instead.
118 * Changed some error messages.
121 * Revision 2.4.3.1 91/10/05 13:08:27 jeffreyh
122 * Added suffix handling and thread handling of variables.
123 * Added new variables: lines, task, thread, work and arg.
124 * Moved db_read_variable and db_write_variable to db_variables.h
125 * as macros, and added db_read_write_variable instead.
126 * Changed some error messages.
129 * Revision 2.4 91/05/14 15:36:57 mrt
130 * Correcting copyright
132 * Revision 2.3 91/02/05 17:07:19 mrt
133 * Changed to new Mach copyright
134 * [91/01/31 16:19:46 mrt]
136 * Revision 2.2 90/08/27 21:53:24 dbg
137 * New db_read/write_variable functions. Should be used instead
138 * of dereferencing valuep directly, which might not be a true
139 * pointer if there is an fcn() access function.
143 * Check for trailing garbage after last expression on command line.
144 * [90/08/10 14:34:54 dbg]
152 * Mach Operating System
153 * Copyright (c) 1991,1990 Carnegie Mellon University
154 * All Rights Reserved.
156 * Permission to use, copy, modify and distribute this software and its
157 * documentation is hereby granted, provided that both the copyright
158 * notice and this permission notice appear in all copies of the
159 * software, derivative works or modified versions, and any portions
160 * thereof, and that both notices appear in supporting documentation.
162 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
163 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
164 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
166 * Carnegie Mellon requests users of this software to return to
168 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
169 * School of Computer Science
170 * Carnegie Mellon University
171 * Pittsburgh PA 15213-3890
173 * any improvements or extensions that they make and grant Carnegie Mellon
174 * the rights to redistribute these changes.
179 * Author: David B. Golub, Carnegie Mellon University
183 #include <machine/db_machdep.h>
184 #include <string.h> /* For strcpy() */
186 #include <ddb/db_lex.h>
187 #include <ddb/db_variables.h>
188 #include <ddb/db_task_thread.h>
189 #include <ddb/db_sym.h>
190 #include <ddb/db_command.h>
191 #include <ddb/db_expr.h>
192 #include <ddb/db_macro.h>
193 #include <ddb/db_output.h> /* For db_printf() */
195 extern db_expr_t db_radix
;
196 extern db_expr_t db_max_width
;
197 extern db_expr_t db_tab_stop_width
;
198 extern db_expr_t db_max_line
;
199 extern db_expr_t db_auto_wrap
;
200 extern db_expr_t db_macro_level
;
201 extern db_expr_t db_auto_completion
;
203 #define DB_NWORK 32 /* number of work variable */
205 db_expr_t db_work
[DB_NWORK
]; /* work variable */
207 struct db_variable db_vars
[] = {
208 { "maxoff", (db_expr_t
*)&db_maxoff
, FCN_NULL
},
209 { "autowrap", &db_auto_wrap
, FCN_NULL
},
210 { "completion", &db_auto_completion
, FCN_NULL
},
211 { "maxwidth", &db_max_width
, FCN_NULL
},
212 { "radix", &db_radix
, FCN_NULL
},
213 { "tabstops", &db_tab_stop_width
, FCN_NULL
},
214 { "lines", &db_max_line
, FCN_NULL
},
215 { "thr_act", 0, db_set_default_act
},
216 { "task", 0, db_get_task_act
,
218 { "work", &db_work
[0], FCN_NULL
,
219 1, 1, 0, DB_NWORK
-1 },
220 { "arg", 0, db_arg_variable
,
221 1, 1, 1, DB_MACRO_NARGS
,
222 1, 0, DB_MACRO_LEVEL
-1, (int *)&db_macro_level
},
224 struct db_variable
*db_evars
= db_vars
+ sizeof(db_vars
)/sizeof(db_vars
[0]);
228 /* Prototypes for functions local to this file.
231 static char *db_get_suffix(
232 register char *suffix
,
233 short *suffix_value
);
235 static boolean_t
db_cmp_variable_name(
236 struct db_variable
*vp
,
238 register db_var_aux_param_t ap
);
240 static int db_find_variable(
241 struct db_variable
**varp
,
242 db_var_aux_param_t ap
);
244 static int db_set_variable(db_expr_t value
);
246 void db_list_variable(void);
250 register char *suffix
,
255 for (value
= 0; *suffix
&& *suffix
!= '.' && *suffix
!= ':'; suffix
++) {
256 if (*suffix
< '0' || *suffix
> '9')
258 value
= value
*10 + *suffix
- '0';
260 *suffix_value
= value
;
267 db_cmp_variable_name(
268 struct db_variable
*vp
,
270 register db_var_aux_param_t ap
)
272 register char *var_np
, *np
;
275 for (np
= name
, var_np
= vp
->name
; *var_np
; ) {
276 if (*np
++ != *var_np
++)
279 for (level
= 0; *np
&& *np
!= ':' && level
< vp
->max_level
; level
++){
280 if ((np
= db_get_suffix(np
, &ap
->suffix
[level
])) == 0)
283 if ((*np
&& *np
!= ':') || level
< vp
->min_level
284 || (level
> 0 && (ap
->suffix
[0] < vp
->low
285 || (vp
->high
>= 0 && ap
->suffix
[0] > vp
->high
))))
287 strcpy(ap
->modif
, (*np
)? np
+1: "");
288 ap
->thr_act
= (db_option(ap
->modif
, 't')?db_default_act
: THR_ACT_NULL
);
290 ap
->hidden_level
= -1;
296 struct db_variable
**varp
,
297 db_var_aux_param_t ap
)
300 struct db_variable
*vp
;
304 for (vp
= db_vars
; vp
< db_evars
; vp
++) {
305 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
310 for (vp
= db_regs
; vp
< db_eregs
; vp
++) {
311 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
316 #if defined(ALTERNATE_REGISTER_DEFS)
317 for (vp
= db_altregs
; vp
< db_ealtregs
; vp
++) {
318 if (db_cmp_variable_name(vp
, db_tok_string
, ap
)) {
323 #endif /* defined(ALTERNATE_REGISTER_DEFS) */
325 db_printf("Unknown variable \"$%s\"\n", db_tok_string
);
331 db_get_variable(db_expr_t
*valuep
)
333 struct db_variable
*vp
;
334 struct db_var_aux_param aux_param
;
335 char modif
[TOK_STRING_SIZE
];
337 aux_param
.modif
= modif
;
338 if (!db_find_variable(&vp
, &aux_param
))
341 db_read_write_variable(vp
, valuep
, DB_VAR_GET
, &aux_param
);
347 db_set_variable(db_expr_t value
)
349 struct db_variable
*vp
;
350 struct db_var_aux_param aux_param
;
351 char modif
[TOK_STRING_SIZE
];
353 aux_param
.modif
= modif
;
354 if (!db_find_variable(&vp
, &aux_param
))
357 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
363 db_read_write_variable(
364 struct db_variable
*vp
,
367 db_var_aux_param_t ap
)
369 int (*func
)(struct db_variable
*, db_expr_t
*,int, db_var_aux_param_t
)
371 struct db_var_aux_param aux_param
;
378 ap
->thr_act
= THR_ACT_NULL
;
380 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
381 db_read_write_variable(vp
, &old_value
, DB_VAR_GET
, ap
);
382 if (func
== FCN_NULL
) {
383 if (rw_flag
== DB_VAR_SET
)
384 vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0] = *valuep
;
386 *valuep
= vp
->valuep
[(ap
->level
)? (ap
->suffix
[0] - vp
->low
): 0];
388 (*func
)(vp
, valuep
, rw_flag
, ap
);
389 if (rw_flag
== DB_VAR_SET
&& vp
->precious
)
390 db_printf("\t$%s:%s<%#x>\t%#8n\t=\t%#8n\n", vp
->name
,
391 ap
->modif
, ap
->thr_act
, old_value
, *valuep
);
395 db_list_variable(void)
397 register struct db_variable
*new;
398 register struct db_variable
*old
;
399 register struct db_variable
*cur
;
406 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
407 if (cur
->min_level
> 0 || cur
->max_level
> 0) {
408 j
= 3 * (cur
->max_level
- cur
->min_level
+ 1) - 1;
409 if (cur
->max_level
> cur
->min_level
)
413 if ((l
= strlen(cur
->name
) + j
) >= len
)
417 old
= (struct db_variable
*)0;
419 new = (struct db_variable
*)0;
420 for (cur
= db_vars
; cur
< db_evars
; cur
++)
421 if ((new == (struct db_variable
*)0 ||
422 strcmp(cur
->name
, new->name
) < 0) &&
423 (old
== (struct db_variable
*)0 ||
424 strcmp(cur
->name
, old
->name
) > 0))
426 if (new == (struct db_variable
*)0)
428 db_reserve_output_position(len
);
429 db_printf(new->name
);
430 j
= strlen(new->name
);
431 if (new->min_level
> 0) {
435 for (i
= new->min_level
- 1; i
> 0; i
--) {
441 if (new->max_level
> new->min_level
) {
448 i
= new->min_level
+ 1;
450 if (new->max_level
> new->min_level
) {
456 while (i
++ < new->max_level
) {
462 if (new->max_level
> new->min_level
) {
477 struct db_variable
*vp
;
478 struct db_var_aux_param aux_param
;
479 char modif
[TOK_STRING_SIZE
];
481 aux_param
.modif
= modif
;
483 if (t
== tIDENT
&& strcmp("help", db_tok_string
) == 0) {
488 db_error("Variable name should be prefixed with $\n");
491 if (!db_find_variable(&vp
, &aux_param
)) {
492 db_error("Unknown variable\n");
500 if (!db_expression(&value
)) {
501 db_error("No value\n");
504 if ((t
= db_read_token()) == tSEMI_COLON
)
509 db_read_write_variable(vp
, &value
, DB_VAR_SET
, &aux_param
);
513 db_show_one_variable(void)
515 struct db_variable
*cur
;
525 struct db_var_aux_param aux_param
;
531 for (cur
= db_vars
; cur
< db_evars
; cur
++)
532 if (db_cmp_variable_name(cur
, db_tok_string
, &aux_param
))
534 if (cur
== db_evars
) {
535 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
536 for (q
= cur
->name
, p
= db_tok_string
; *q
&& *p
== *q
; p
++,q
++)
541 if (cur
== db_evars
) {
542 db_error("Unknown variable\n");
546 for (i
= 0; *p
&& *p
!= ':' && i
< cur
->max_level
; i
++, p
= q
)
547 if ((q
= db_get_suffix(p
, &aux_param
.suffix
[i
])) == 0)
550 if ((*p
&& *p
!= ':') ||
551 (i
> 0 && (aux_param
.suffix
[0] < cur
->low
||
553 aux_param
.suffix
[0] > cur
->high
)))) {
554 db_error("Unknown variable format\n");
558 strcpy(aux_param
.modif
, *p
? p
+ 1 : "");
559 aux_param
.thr_act
= (db_option(aux_param
.modif
, 't') ?
560 db_default_act
: THR_ACT_NULL
);
563 if (cur
->hidden_level
)
564 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
565 *cur
->hidden_levelp
<= cur
->hidden_high
) {
567 aux_param
.hidden_level
= h
= *cur
->hidden_levelp
;
570 aux_param
.hidden_level
= h
= cur
->hidden_low
;
572 for (k
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->high
;
577 aux_param
.hidden_level
= -1;
579 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
582 if (cur
->min_level
> 0) {
584 for (k
= aux_param
.level
> 0 ?
585 aux_param
.suffix
[0] : cur
->high
; k
> 9; k
/= 10)
589 if (cur
->hidden_level
&& hidden_level
== 0) {
591 for (k
= aux_param
.hidden_level
>= 0 ?
592 aux_param
.hidden_level
: cur
->hidden_high
; k
> 9; k
/= 10)
596 len
= strlen(cur
->name
) + j
;
597 i
= low
= aux_param
.level
> 0 ? aux_param
.suffix
[0] : cur
->low
;
600 db_printf(cur
->name
);
601 j
= strlen(cur
->name
);
602 if (cur
->high
>= 0) {
603 if (cur
->min_level
> 0) {
606 for (k
= i
; k
> 9; k
/= 10)
609 if (cur
->hidden_level
&& hidden_level
== 0) {
611 for (k
= i
; k
> 9; k
/= 10)
613 while (sl
++ < slen
) {
617 db_printf("[%d]", h
);
619 for (k
= h
; k
> 9; k
/= 10)
630 aux_param
.suffix
[0] = i
;
631 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
633 db_printf("%#n", *(cur
->valuep
+ i
));
634 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
636 if (name
!= (char *)0 && offset
<= db_maxoff
&&
637 offset
!= *(cur
->valuep
+ i
)) {
638 db_printf("\t%s", name
);
640 db_printf("+%#r", offset
);
646 if (aux_param
.level
> 0 || i
++ == cur
->high
) {
647 if (!cur
->hidden_level
||
649 h
++ == cur
->hidden_high
)
651 aux_param
.hidden_level
= h
;
658 db_show_variable(void)
660 struct db_variable
*cur
;
671 struct db_var_aux_param aux_param
;
675 switch(t
= db_read_token()) {
682 t1
= db_read_token();
684 db_show_one_variable();
687 db_error("Not a variable name after $\n");
692 db_error("Variable name should be prefixed with $\n");
699 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
700 if ((cur
->min_level
== 0 && !cur
->hidden_level
) || cur
->high
< 0)
703 if (cur
->min_level
> 0) {
705 for (k
= cur
->high
; k
> 9; k
/= 10)
709 if (cur
->hidden_level
&&
710 (*cur
->hidden_levelp
< cur
->hidden_low
||
711 *cur
->hidden_levelp
> cur
->hidden_high
)) {
713 for (k
= cur
->hidden_high
; k
> 9; k
/= 10)
717 if ((l
= strlen(cur
->name
) + j
) >= len
)
721 aux_param
.modif
= "";
723 aux_param
.thr_act
= THR_ACT_NULL
;
725 for (cur
= db_vars
; cur
< db_evars
; cur
++) {
727 if (cur
->hidden_level
) {
728 if (*cur
->hidden_levelp
>= cur
->hidden_low
&&
729 *cur
->hidden_levelp
<= cur
->hidden_high
) {
730 h
= cur
->hidden_low
- 1;
731 aux_param
.hidden_level
= *cur
->hidden_levelp
;
734 aux_param
.hidden_level
= cur
->hidden_low
;
737 for (k
= cur
->high
; k
> 9; k
/= 10)
740 aux_param
.hidden_level
= -1;
742 if (cur
!= db_vars
&& cur
->high
>= 0 &&
743 (cur
->min_level
> 0 || cur
->hidden_level
))
747 db_printf(cur
->name
);
748 j
= strlen(cur
->name
);
749 if (cur
->high
>= 0) {
750 if (cur
->min_level
> 0) {
753 for (k
= i
; k
> 9; k
/= 10)
756 if (cur
->hidden_level
&& h
>= cur
->hidden_low
) {
758 for (k
= i
; k
> 9; k
/= 10)
760 while (sl
++ < slen
) {
764 db_printf("[%d]", h
);
766 for (k
= h
; k
> 9; k
/= 10)
776 aux_param
.suffix
[0] = i
;
777 (*cur
->fcn
)(cur
, (db_expr_t
*)0, DB_VAR_SHOW
, &aux_param
);
779 db_printf("%#n", *(cur
->valuep
+ i
));
780 db_find_xtrn_task_sym_and_offset(*(cur
->valuep
+ i
), &name
,
782 if (name
!= (char *)0 && offset
<= db_maxoff
&&
783 offset
!= *(cur
->valuep
+ i
)) {
784 db_printf("\t%s", name
);
786 db_printf("+%#r", offset
);
792 if (i
++ == cur
->high
) {
793 if (!cur
->hidden_level
|| h
++ == cur
->hidden_high
)
795 aux_param
.hidden_level
= h
;
803 * given a name of a machine register, return a variable pointer to it.
809 register db_variable_t regp
;
811 if ( s
== (char *)0 )
814 for (regp
= db_regs
; regp
< db_eregs
; regp
++) {
815 if ( strcmp( s
, regp
->name
) == 0 )