]>
git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_input.c
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.3.10.2 1994/09/23 01:19:37 ezf
38 * change marker to not FREE
39 * [1994/09/22 21:10:05 ezf]
41 * Revision 1.3.10.1 1994/06/11 21:11:48 bolinger
42 * Merge up to NMK17.2.
43 * [1994/06/11 20:01:41 bolinger]
45 * Revision 1.3.8.2 1994/02/11 14:21:41 paire
46 * Added string.h header file for strlen declaration.
49 * Revision 1.3.8.1 1994/02/08 10:57:55 bernadat
50 * Added db_auto_completion variable.
53 * Added support of symbol completion by typing '\t'.
57 * Revision 1.3.2.4 1993/08/11 20:37:51 elliston
58 * Add ANSI Prototypes. CR #9523.
59 * [1993/08/11 03:33:21 elliston]
61 * Revision 1.3.2.3 1993/07/27 18:27:30 elliston
62 * Add ANSI prototypes. CR #9523.
63 * [1993/07/27 18:12:01 elliston]
65 * Revision 1.3.2.2 1993/06/09 02:20:13 gm
66 * CR9176 - ANSI C violations: trailing tokens on CPP
67 * directives, extra semicolons after decl_ ..., asm keywords
68 * [1993/06/07 18:57:14 jeffc]
70 * Added to OSF/1 R1.3 from NMK15.0.
71 * [1993/06/02 20:56:26 jeffc]
73 * Revision 1.3 1993/04/19 16:02:17 devrcs
74 * Replaced ^R (redraw) with ^L [barbou@gr.osf.org]
76 * Added ^R and ^S commands for history search commands
77 * ^U does not erase end of the line anymore. (only erases
78 * from the beginning of the line to current position).
81 * ^C now erases the entire line. [barbou@gr.osf.org]
84 * Fixed history management: Do not store repeated typed
85 * command. Null terminate current command in case it is a
86 * substring of the last command.
89 * Revision 1.2 1992/11/25 01:04:24 robert
90 * integrate changes for norma_14 below
92 * Philippe Bernadat (bernadat) at gr.osf.org 02-Oct-92
93 * Fixed history management: Do not store repeated typed
94 * command. Null terminate current command in case it is a
95 * substring of the last command.
96 * [1992/11/20 00:56:07 robert]
98 * integrate changes below for norma_14
99 * [1992/11/13 19:21:34 robert]
101 * Revision 1.1 1992/09/30 02:01:08 robert
108 * Revision 2.7.3.2 92/09/15 17:14:26 jeffreyh
109 * Fixed history code. (Only one char. out of 2 was checked to
110 * compare to last command)
111 * [barbou@gr.osf.org]
113 * Revision 2.7.3.1 92/03/03 16:13:30 jeffreyh
114 * Pick up changes from TRUNK
115 * [92/02/26 10:59:36 jeffreyh]
117 * Revision 2.8 92/02/19 15:07:44 elf
118 * Added delete_line (Ctrl-U).
121 * Added command line history. Ctrl-P = previous, Ctrl-N = next. If
122 * DB_HISTORY_SIZE is 0 then command history is disabled.
125 * Revision 2.7 91/10/09 16:00:03 af
126 * Revision 2.6.2.1 91/10/05 13:06:12 jeffreyh
127 * Fixed incorrect db_lbuf_end setting.
130 * Revision 2.6.2.1 91/10/05 13:06:12 jeffreyh
131 * Fixed incorrect db_lbuf_end setting.
134 * Revision 2.6 91/07/09 23:15:49 danner
135 * Add include of machine/db_machdep.h to allow machine-specific
136 * overrides via defines.
139 * Revision 2.5 91/05/14 15:34:03 mrt
140 * Correcting copyright
142 * Revision 2.4 91/02/14 14:41:53 mrt
143 * Add input line editing.
146 * Revision 2.3 91/02/05 17:06:32 mrt
147 * Changed to new Mach copyright
148 * [91/01/31 16:18:13 mrt]
150 * Revision 2.2 90/08/27 21:51:03 dbg
159 * Mach Operating System
160 * Copyright (c) 1991,1990 Carnegie Mellon University
161 * All Rights Reserved.
163 * Permission to use, copy, modify and distribute this software and its
164 * documentation is hereby granted, provided that both the copyright
165 * notice and this permission notice appear in all copies of the
166 * software, derivative works or modified versions, and any portions
167 * thereof, and that both notices appear in supporting documentation.
169 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
170 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
171 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
173 * Carnegie Mellon requests users of this software to return to
175 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
176 * School of Computer Science
177 * Carnegie Mellon University
178 * Pittsburgh PA 15213-3890
180 * any improvements or extensions that they make and grant Carnegie Mellon
181 * the rights to redistribute these changes.
186 * Author: David B. Golub, Carnegie Mellon University
191 #include <mach/boolean.h>
192 #include <machine/db_machdep.h>
193 #include <kern/misc_protos.h>
194 #include <ddb/db_output.h>
195 #include <ddb/db_lex.h>
196 #include <ddb/db_command.h>
197 #include <ddb/db_input.h>
198 #include <ddb/db_sym.h>
200 #ifndef DB_HISTORY_SIZE
201 #define DB_HISTORY_SIZE 4000
202 #endif /* DB_HISTORY_SIZE */
205 * Character input and editing.
209 * We don't track output position while editing input,
210 * since input always ends with a new-line. We just
211 * reset the line position at the end.
213 char * db_lbuf_start
; /* start of input line buffer */
214 char * db_lbuf_end
; /* end of input line buffer */
215 char * db_lc
; /* current character */
216 char * db_le
; /* one past last character */
217 int db_completion
; /* number of incomplete symbols matched */
218 int db_auto_completion
= 10; /* number of line to display without asking */
219 #if DB_HISTORY_SIZE != 0
220 char db_history
[DB_HISTORY_SIZE
]; /* start of history buffer */
221 int db_history_size
= DB_HISTORY_SIZE
;/* size of history buffer */
222 char * db_history_curr
= db_history
; /* start of current line */
223 char * db_history_last
= db_history
; /* start of last line */
224 char * db_history_prev
= (char *) 0; /* start of previous line */
225 int db_hist_unmodified
= 0; /* unmodified line from history */
226 int db_hist_search
= 0; /* are we in hist search mode ? */
227 char db_hist_search_string
[DB_LEX_LINE_SIZE
];/* the string to look for */
228 int db_hist_ignore_dups
= 0; /* don't duplicate commands in hist */
231 #define CTRL(c) ((c) & 0x1f)
232 #define isspace(c) ((c) == ' ' || (c) == '\t')
238 /* Prototypes for functions local to this file. XXX -- should be static!
252 void db_delete_line(void);
254 boolean_t
db_hist_substring(
258 boolean_t
db_inputchar(int c
);
260 extern jmp_buf_t
*db_recover
;
281 * Delete N characters, forward or backward
294 db_putnchars(BACKUP
, n
);
296 for (p
= db_lc
; p
< db_le
-n
; p
++) {
300 db_putnchars(BLANK
, n
);
301 db_putnchars(BACKUP
, db_le
- db_lc
);
308 db_delete(db_le
- db_lc
, DEL_FWD
);
309 db_delete(db_lc
- db_lbuf_start
, DEL_BWD
);
310 db_le
= db_lc
= db_lbuf_start
;
313 #if DB_HISTORY_SIZE != 0
314 #define INC_DB_CURR() \
317 if (db_history_curr > \
318 db_history + db_history_size - 1) \
319 db_history_curr = db_history; \
321 #define DEC_DB_CURR() \
324 if (db_history_curr < db_history) \
325 db_history_curr = db_history + \
326 db_history_size - 1; \
330 /* returs TRUE if "substring" is a substring of "string" */
336 register char *cp1
, *cp2
;
345 while (cp2
> substring
) {
349 while (cp1
>= string
) {
354 while (*cp2
&& *cp2
== *cp3
) {
365 /* returns TRUE at end-of-line */
377 switch(db_completion
) {
380 db_prev
= db_recover
;
381 if (_setjmp(db_recover
= &db_jmpbuf
) == 0 &&
382 (c
== 'y' || c
== ' ' || c
== '\t'))
383 db_print_completion(db_tok_string
);
384 db_recover
= db_prev
;
388 if (db_le
> db_lbuf_start
) {
389 for (start
= db_lbuf_start
; start
< db_le
; start
++)
391 db_putnchars(BACKUP
, db_le
- db_lc
);
400 db_printf("\nThere are %d possibilities. ", db_completion
);
401 db_printf("Do you really wish to see them all [n] ? ");
402 db_force_whitespace();
413 /* symbol completion */
414 if (db_lc
== db_lbuf_start
|| db_auto_completion
== 0)
416 if (db_le
== db_lbuf_end
) {
421 while (start
>= db_lbuf_start
&&
422 ((*start
>= 'A' && *start
<= 'Z') ||
423 (*start
>= 'a' && *start
<= 'z') ||
424 (*start
>= '0' && *start
<= '9') ||
425 *start
== '_' || *start
== ':'))
427 if (start
== db_lc
- 1)
429 if (start
> db_lbuf_start
&& *start
== '$') {
437 } while (start
!= db_lc
&&
438 sym
!= db_tok_string
+ sizeof(db_tok_string
));
439 if (sym
== db_tok_string
+ sizeof(db_tok_string
)) {
444 db_completion
= db_lookup_incomplete(db_tok_string
,
445 sizeof(db_tok_string
));
446 if (db_completion
== 0) {
452 len
= strlen(db_tok_string
) - (start
- restart
);
453 if (db_completion
== 1 &&
455 (db_le
> db_lc
) && *db_lc
!= ' '))
457 for (p
= db_le
- 1; p
>= db_lc
; p
--)
460 for (sym
= &db_tok_string
[start
- restart
];
464 if (db_completion
== 1 || db_completion
> db_auto_completion
) {
465 for (sym
= &db_tok_string
[start
- restart
];
468 if (db_completion
== 1) {
469 if (db_le
== db_lc
||
470 (db_le
> db_lc
) && *db_lc
!= ' ') {
476 db_putstring(db_lc
, db_le
- db_lc
);
477 db_putnchars(BACKUP
, db_le
- db_lc
);
480 if (db_completion
> 1) {
482 if (db_completion
<= db_auto_completion
) {
484 db_print_completion(db_tok_string
);
488 if (db_le
> db_lbuf_start
) {
489 for (start
= db_lbuf_start
; start
< db_le
; start
++)
491 db_putnchars(BACKUP
, db_le
- db_lc
);
498 /* back up one character */
499 if (db_lc
> db_lbuf_start
) {
505 /* forward one character */
512 /* beginning of line */
513 while (db_lc
> db_lbuf_start
) {
520 while (db_lc
< db_le
) {
527 /* erase previous character */
528 if (db_lc
> db_lbuf_start
)
529 db_delete(1, DEL_BWD
);
532 /* erase next character */
534 db_delete(1, DEL_FWD
);
537 /* delete to end of line */
539 db_delete(db_le
- db_lc
, DEL_FWD
);
542 /* delete to beginning of line */
543 if (db_lc
> db_lbuf_start
)
544 db_delete(db_lc
- db_lbuf_start
, DEL_BWD
);
547 /* twiddle last 2 characters */
548 if (db_lc
>= db_lbuf_start
+ 2) {
550 db_lc
[-2] = db_lc
[-1];
561 #if DB_HISTORY_SIZE != 0
562 db_history_curr
= db_history_last
;
563 if (c
== CTRL('g') && db_hist_search
) {
565 for (p
= db_hist_search_string
, db_le
= db_lbuf_start
;
571 db_putstring(db_lbuf_start
, db_le
- db_lbuf_start
);
575 #if DB_HISTORY_SIZE != 0
577 if (db_hist_search
++ == 0) {
578 /* starting an history lookup */
579 register char *cp1
, *cp2
;
580 for (cp1
= db_lbuf_start
, cp2
= db_hist_search_string
;
590 char * old_history_curr
= db_history_curr
;
592 if (db_hist_unmodified
++ == 0)
593 db_hist_unmodified
++;
595 while (db_history_curr
!= db_history_last
) {
597 if (*db_history_curr
== '\0') {
599 if (db_hist_search
<= 1) {
600 if (*db_history_curr
== '\0')
606 if (*db_history_curr
== '\0') {
608 db_history_curr
= old_history_curr
;
612 if (db_history_curr
!= db_history_last
&&
613 db_hist_substring(db_history_curr
,
614 db_hist_search_string
)) {
621 if (db_history_curr
== db_history_last
) {
623 db_history_curr
= old_history_curr
;
628 for (p
= db_history_curr
, db_le
= db_lbuf_start
;
631 if (p
== db_history
+ db_history_size
) {
637 db_putstring(db_lbuf_start
, db_le
- db_lbuf_start
);
642 if (db_hist_search
++ == 0) {
643 /* starting an history lookup */
644 register char *cp1
, *cp2
;
645 for (cp1
= db_lbuf_start
, cp2
= db_hist_search_string
;
655 char *old_history_curr
= db_history_curr
;
657 if (db_hist_unmodified
++ == 0)
658 db_hist_unmodified
++;
659 while (db_history_curr
!= db_history_last
) {
660 if (*db_history_curr
== '\0') {
661 if (db_hist_search
<= 1)
664 if (db_history_curr
!= db_history_last
&&
665 db_hist_substring(db_history_curr
,
666 db_hist_search_string
)) {
674 if (db_history_curr
!= db_history_last
) {
676 if (db_history_curr
!= db_history_last
) {
679 for (p
= db_history_curr
,
680 db_le
= db_lbuf_start
; *p
;) {
682 if (p
== db_history
+
689 db_putstring(db_lbuf_start
,
690 db_le
- db_lbuf_start
);
693 db_history_curr
= old_history_curr
;
697 db_history_curr
= old_history_curr
;
702 /* refresh the command line */
704 db_putstring("^L\n", 3);
705 if (db_le
> db_lbuf_start
) {
706 db_putstring(db_lbuf_start
, db_le
- db_lbuf_start
);
707 db_putnchars(BACKUP
, db_le
- db_lc
);
712 #if DB_HISTORY_SIZE != 0
713 /* Check if it same than previous line */
714 if (db_history_prev
) {
715 register char *pp
, *pc
;
717 /* Is it unmodified */
718 for (p
= db_history_prev
, pc
= db_lbuf_start
;
719 pc
!= db_le
&& *p
;) {
722 if (++p
== db_history
+ db_history_size
) {
725 if (++pc
== db_history
+ db_history_size
) {
729 if (!*p
&& pc
== db_le
) {
730 /* Repeted previous line, not saved */
731 db_history_curr
= db_history_last
;
734 db_hist_unmodified
= 0;
738 if (db_le
!= db_lbuf_start
&&
739 (db_hist_unmodified
== 0 || !db_hist_ignore_dups
)) {
740 db_history_prev
= db_history_last
;
741 for (p
= db_lbuf_start
; p
!= db_le
; p
++) {
742 *db_history_last
++ = *p
;
743 if (db_history_last
== db_history
+
745 db_history_last
= db_history
;
748 *db_history_last
++ = '\0';
750 db_history_curr
= db_history_last
;
754 db_hist_unmodified
= 0;
757 if (db_le
== db_lbuf_end
) {
760 else if (c
>= ' ' && c
<= '~') {
761 for (p
= db_le
; p
> db_lc
; p
--)
766 db_putstring(db_lc
, db_le
- db_lc
);
767 db_putnchars(BACKUP
, db_le
- db_lc
);
773 if (db_hist_unmodified
)
774 db_hist_unmodified
--;
783 db_force_whitespace(); /* synch output position */
785 db_lbuf_start
= lstart
;
786 db_lbuf_end
= lstart
+ lsize
- 1;
790 while (!db_inputchar(cngetc()))
793 db_putchar('\n'); /* synch output position */
796 return (db_le
- db_lbuf_start
);
800 db_check_interrupt(void)
806 case -1: /* no character */
818 } while (c
!= CTRL('q'));