]>
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_OSREFERENCE_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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
34 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
35 * Import of Mac OS X kernel (~semeria)
37 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
38 * Import of OSF Mach kernel (~mburg)
40 * Revision 1.3.10.2 1994/09/23 01:19:37 ezf
41 * change marker to not FREE
42 * [1994/09/22 21:10:05 ezf]
44 * Revision 1.3.10.1 1994/06/11 21:11:48 bolinger
45 * Merge up to NMK17.2.
46 * [1994/06/11 20:01:41 bolinger]
48 * Revision 1.3.8.2 1994/02/11 14:21:41 paire
49 * Added string.h header file for strlen declaration.
52 * Revision 1.3.8.1 1994/02/08 10:57:55 bernadat
53 * Added db_auto_completion variable.
56 * Added support of symbol completion by typing '\t'.
60 * Revision 1.3.2.4 1993/08/11 20:37:51 elliston
61 * Add ANSI Prototypes. CR #9523.
62 * [1993/08/11 03:33:21 elliston]
64 * Revision 1.3.2.3 1993/07/27 18:27:30 elliston
65 * Add ANSI prototypes. CR #9523.
66 * [1993/07/27 18:12:01 elliston]
68 * Revision 1.3.2.2 1993/06/09 02:20:13 gm
69 * CR9176 - ANSI C violations: trailing tokens on CPP
70 * directives, extra semicolons after decl_ ..., asm keywords
71 * [1993/06/07 18:57:14 jeffc]
73 * Added to OSF/1 R1.3 from NMK15.0.
74 * [1993/06/02 20:56:26 jeffc]
76 * Revision 1.3 1993/04/19 16:02:17 devrcs
77 * Replaced ^R (redraw) with ^L [barbou@gr.osf.org]
79 * Added ^R and ^S commands for history search commands
80 * ^U does not erase end of the line anymore. (only erases
81 * from the beginning of the line to current position).
84 * ^C now erases the entire line. [barbou@gr.osf.org]
87 * Fixed history management: Do not store repeated typed
88 * command. Null terminate current command in case it is a
89 * substring of the last command.
92 * Revision 1.2 1992/11/25 01:04:24 robert
93 * integrate changes for norma_14 below
95 * Philippe Bernadat (bernadat) at gr.osf.org 02-Oct-92
96 * Fixed history management: Do not store repeated typed
97 * command. Null terminate current command in case it is a
98 * substring of the last command.
99 * [1992/11/20 00:56:07 robert]
101 * integrate changes below for norma_14
102 * [1992/11/13 19:21:34 robert]
104 * Revision 1.1 1992/09/30 02:01:08 robert
111 * Revision 2.7.3.2 92/09/15 17:14:26 jeffreyh
112 * Fixed history code. (Only one char. out of 2 was checked to
113 * compare to last command)
114 * [barbou@gr.osf.org]
116 * Revision 2.7.3.1 92/03/03 16:13:30 jeffreyh
117 * Pick up changes from TRUNK
118 * [92/02/26 10:59:36 jeffreyh]
120 * Revision 2.8 92/02/19 15:07:44 elf
121 * Added delete_line (Ctrl-U).
124 * Added command line history. Ctrl-P = previous, Ctrl-N = next. If
125 * DB_HISTORY_SIZE is 0 then command history is disabled.
128 * Revision 2.7 91/10/09 16:00:03 af
129 * Revision 2.6.2.1 91/10/05 13:06:12 jeffreyh
130 * Fixed incorrect db_lbuf_end setting.
133 * Revision 2.6.2.1 91/10/05 13:06:12 jeffreyh
134 * Fixed incorrect db_lbuf_end setting.
137 * Revision 2.6 91/07/09 23:15:49 danner
138 * Add include of machine/db_machdep.h to allow machine-specific
139 * overrides via defines.
142 * Revision 2.5 91/05/14 15:34:03 mrt
143 * Correcting copyright
145 * Revision 2.4 91/02/14 14:41:53 mrt
146 * Add input line editing.
149 * Revision 2.3 91/02/05 17:06:32 mrt
150 * Changed to new Mach copyright
151 * [91/01/31 16:18:13 mrt]
153 * Revision 2.2 90/08/27 21:51:03 dbg
162 * Mach Operating System
163 * Copyright (c) 1991,1990 Carnegie Mellon University
164 * All Rights Reserved.
166 * Permission to use, copy, modify and distribute this software and its
167 * documentation is hereby granted, provided that both the copyright
168 * notice and this permission notice appear in all copies of the
169 * software, derivative works or modified versions, and any portions
170 * thereof, and that both notices appear in supporting documentation.
172 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
173 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
174 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
176 * Carnegie Mellon requests users of this software to return to
178 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
179 * School of Computer Science
180 * Carnegie Mellon University
181 * Pittsburgh PA 15213-3890
183 * any improvements or extensions that they make and grant Carnegie Mellon
184 * the rights to redistribute these changes.
189 * Author: David B. Golub, Carnegie Mellon University
194 #include <mach/boolean.h>
195 #include <machine/db_machdep.h>
196 #include <kern/misc_protos.h>
197 #include <ddb/db_output.h>
198 #include <ddb/db_lex.h>
199 #include <ddb/db_command.h>
200 #include <ddb/db_input.h>
201 #include <ddb/db_sym.h>
203 #ifndef DB_HISTORY_SIZE
204 #define DB_HISTORY_SIZE 4000
205 #endif /* DB_HISTORY_SIZE */
208 * Character input and editing.
212 * We don't track output position while editing input,
213 * since input always ends with a new-line. We just
214 * reset the line position at the end.
216 char * db_lbuf_start
; /* start of input line buffer */
217 char * db_lbuf_end
; /* end of input line buffer */
218 char * db_lc
; /* current character */
219 char * db_le
; /* one past last character */
220 int db_completion
; /* number of incomplete symbols matched */
221 int db_auto_completion
= 10; /* number of line to display without asking */
222 #if DB_HISTORY_SIZE != 0
223 char db_history
[DB_HISTORY_SIZE
]; /* start of history buffer */
224 int db_history_size
= DB_HISTORY_SIZE
;/* size of history buffer */
225 char * db_history_curr
= db_history
; /* start of current line */
226 char * db_history_last
= db_history
; /* start of last line */
227 char * db_history_prev
= (char *) 0; /* start of previous line */
228 int db_hist_unmodified
= 0; /* unmodified line from history */
229 int db_hist_search
= 0; /* are we in hist search mode ? */
230 char db_hist_search_string
[DB_LEX_LINE_SIZE
];/* the string to look for */
231 int db_hist_ignore_dups
= 0; /* don't duplicate commands in hist */
234 #define CTRL(c) ((c) & 0x1f)
235 #define isspace(c) ((c) == ' ' || (c) == '\t')
241 /* Prototypes for functions local to this file. XXX -- should be static!
255 void db_delete_line(void);
257 boolean_t
db_hist_substring(
261 boolean_t
db_inputchar(int c
);
263 extern jmp_buf_t
*db_recover
;
284 * Delete N characters, forward or backward
297 db_putnchars(BACKUP
, n
);
299 for (p
= db_lc
; p
< db_le
-n
; p
++) {
303 db_putnchars(BLANK
, n
);
304 db_putnchars(BACKUP
, db_le
- db_lc
);
311 db_delete(db_le
- db_lc
, DEL_FWD
);
312 db_delete(db_lc
- db_lbuf_start
, DEL_BWD
);
313 db_le
= db_lc
= db_lbuf_start
;
316 #if DB_HISTORY_SIZE != 0
317 #define INC_DB_CURR() \
320 if (db_history_curr > \
321 db_history + db_history_size - 1) \
322 db_history_curr = db_history; \
324 #define DEC_DB_CURR() \
327 if (db_history_curr < db_history) \
328 db_history_curr = db_history + \
329 db_history_size - 1; \
333 /* returs TRUE if "substring" is a substring of "string" */
339 register char *cp1
, *cp2
;
348 while (cp2
> substring
) {
352 while (cp1
>= string
) {
357 while (*cp2
&& *cp2
== *cp3
) {
368 /* returns TRUE at end-of-line */
380 switch(db_completion
) {
383 db_prev
= db_recover
;
384 if (_setjmp(db_recover
= &db_jmpbuf
) == 0 &&
385 (c
== 'y' || c
== ' ' || c
== '\t'))
386 db_print_completion(db_tok_string
);
387 db_recover
= db_prev
;
391 if (db_le
> db_lbuf_start
) {
392 for (start
= db_lbuf_start
; start
< db_le
; start
++)
394 db_putnchars(BACKUP
, db_le
- db_lc
);
403 db_printf("\nThere are %d possibilities. ", db_completion
);
404 db_printf("Do you really wish to see them all [n] ? ");
405 db_force_whitespace();
416 /* symbol completion */
417 if (db_lc
== db_lbuf_start
|| db_auto_completion
== 0)
419 if (db_le
== db_lbuf_end
) {
424 while (start
>= db_lbuf_start
&&
425 ((*start
>= 'A' && *start
<= 'Z') ||
426 (*start
>= 'a' && *start
<= 'z') ||
427 (*start
>= '0' && *start
<= '9') ||
428 *start
== '_' || *start
== ':'))
430 if (start
== db_lc
- 1)
432 if (start
> db_lbuf_start
&& *start
== '$') {
440 } while (start
!= db_lc
&&
441 sym
!= db_tok_string
+ sizeof(db_tok_string
));
442 if (sym
== db_tok_string
+ sizeof(db_tok_string
)) {
447 db_completion
= db_lookup_incomplete(db_tok_string
,
448 sizeof(db_tok_string
));
449 if (db_completion
== 0) {
455 len
= strlen(db_tok_string
) - (start
- restart
);
456 if (db_completion
== 1 &&
458 (db_le
> db_lc
) && *db_lc
!= ' '))
460 for (p
= db_le
- 1; p
>= db_lc
; p
--)
463 for (sym
= &db_tok_string
[start
- restart
];
467 if (db_completion
== 1 || db_completion
> db_auto_completion
) {
468 for (sym
= &db_tok_string
[start
- restart
];
471 if (db_completion
== 1) {
472 if (db_le
== db_lc
||
473 (db_le
> db_lc
) && *db_lc
!= ' ') {
479 db_putstring(db_lc
, db_le
- db_lc
);
480 db_putnchars(BACKUP
, db_le
- db_lc
);
483 if (db_completion
> 1) {
485 if (db_completion
<= db_auto_completion
) {
487 db_print_completion(db_tok_string
);
491 if (db_le
> db_lbuf_start
) {
492 for (start
= db_lbuf_start
; start
< db_le
; start
++)
494 db_putnchars(BACKUP
, db_le
- db_lc
);
501 /* back up one character */
502 if (db_lc
> db_lbuf_start
) {
508 /* forward one character */
515 /* beginning of line */
516 while (db_lc
> db_lbuf_start
) {
523 while (db_lc
< db_le
) {
530 /* erase previous character */
531 if (db_lc
> db_lbuf_start
)
532 db_delete(1, DEL_BWD
);
535 /* erase next character */
537 db_delete(1, DEL_FWD
);
540 /* delete to end of line */
542 db_delete(db_le
- db_lc
, DEL_FWD
);
545 /* delete to beginning of line */
546 if (db_lc
> db_lbuf_start
)
547 db_delete(db_lc
- db_lbuf_start
, DEL_BWD
);
550 /* twiddle last 2 characters */
551 if (db_lc
>= db_lbuf_start
+ 2) {
553 db_lc
[-2] = db_lc
[-1];
564 #if DB_HISTORY_SIZE != 0
565 db_history_curr
= db_history_last
;
566 if (c
== CTRL('g') && db_hist_search
) {
568 for (p
= db_hist_search_string
, db_le
= db_lbuf_start
;
574 db_putstring(db_lbuf_start
, db_le
- db_lbuf_start
);
578 #if DB_HISTORY_SIZE != 0
580 if (db_hist_search
++ == 0) {
581 /* starting an history lookup */
582 register char *cp1
, *cp2
;
583 for (cp1
= db_lbuf_start
, cp2
= db_hist_search_string
;
593 char * old_history_curr
= db_history_curr
;
595 if (db_hist_unmodified
++ == 0)
596 db_hist_unmodified
++;
598 while (db_history_curr
!= db_history_last
) {
600 if (*db_history_curr
== '\0') {
602 if (db_hist_search
<= 1) {
603 if (*db_history_curr
== '\0')
609 if (*db_history_curr
== '\0') {
611 db_history_curr
= old_history_curr
;
615 if (db_history_curr
!= db_history_last
&&
616 db_hist_substring(db_history_curr
,
617 db_hist_search_string
)) {
624 if (db_history_curr
== db_history_last
) {
626 db_history_curr
= old_history_curr
;
631 for (p
= db_history_curr
, db_le
= db_lbuf_start
;
634 if (p
== db_history
+ db_history_size
) {
640 db_putstring(db_lbuf_start
, db_le
- db_lbuf_start
);
645 if (db_hist_search
++ == 0) {
646 /* starting an history lookup */
647 register char *cp1
, *cp2
;
648 for (cp1
= db_lbuf_start
, cp2
= db_hist_search_string
;
658 char *old_history_curr
= db_history_curr
;
660 if (db_hist_unmodified
++ == 0)
661 db_hist_unmodified
++;
662 while (db_history_curr
!= db_history_last
) {
663 if (*db_history_curr
== '\0') {
664 if (db_hist_search
<= 1)
667 if (db_history_curr
!= db_history_last
&&
668 db_hist_substring(db_history_curr
,
669 db_hist_search_string
)) {
677 if (db_history_curr
!= db_history_last
) {
679 if (db_history_curr
!= db_history_last
) {
682 for (p
= db_history_curr
,
683 db_le
= db_lbuf_start
; *p
;) {
685 if (p
== db_history
+
692 db_putstring(db_lbuf_start
,
693 db_le
- db_lbuf_start
);
696 db_history_curr
= old_history_curr
;
700 db_history_curr
= old_history_curr
;
705 /* refresh the command line */
707 db_putstring("^L\n", 3);
708 if (db_le
> db_lbuf_start
) {
709 db_putstring(db_lbuf_start
, db_le
- db_lbuf_start
);
710 db_putnchars(BACKUP
, db_le
- db_lc
);
715 #if DB_HISTORY_SIZE != 0
716 /* Check if it same than previous line */
717 if (db_history_prev
) {
718 register char *pp
, *pc
;
720 /* Is it unmodified */
721 for (p
= db_history_prev
, pc
= db_lbuf_start
;
722 pc
!= db_le
&& *p
;) {
725 if (++p
== db_history
+ db_history_size
) {
728 if (++pc
== db_history
+ db_history_size
) {
732 if (!*p
&& pc
== db_le
) {
733 /* Repeted previous line, not saved */
734 db_history_curr
= db_history_last
;
737 db_hist_unmodified
= 0;
741 if (db_le
!= db_lbuf_start
&&
742 (db_hist_unmodified
== 0 || !db_hist_ignore_dups
)) {
743 db_history_prev
= db_history_last
;
744 for (p
= db_lbuf_start
; p
!= db_le
; p
++) {
745 *db_history_last
++ = *p
;
746 if (db_history_last
== db_history
+
748 db_history_last
= db_history
;
751 *db_history_last
++ = '\0';
753 db_history_curr
= db_history_last
;
757 db_hist_unmodified
= 0;
760 if (db_le
== db_lbuf_end
) {
763 else if (c
>= ' ' && c
<= '~') {
764 for (p
= db_le
; p
> db_lc
; p
--)
769 db_putstring(db_lc
, db_le
- db_lc
);
770 db_putnchars(BACKUP
, db_le
- db_lc
);
776 if (db_hist_unmodified
)
777 db_hist_unmodified
--;
786 db_force_whitespace(); /* synch output position */
788 db_lbuf_start
= lstart
;
789 db_lbuf_end
= lstart
+ lsize
- 1;
793 while (!db_inputchar(cngetc()))
796 db_putchar('\n'); /* synch output position */
799 return (db_le
- db_lbuf_start
);
803 db_check_interrupt(void)
809 case -1: /* no character */
821 } while (c
!= CTRL('q'));