]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ddb/db_input.c
xnu-792.17.14.tar.gz
[apple/xnu.git] / osfmk / ddb / db_input.c
1 /*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
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.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*
29 * @OSF_COPYRIGHT@
30 */
31 /*
32 * HISTORY
33 *
34 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
35 * Import of Mac OS X kernel (~semeria)
36 *
37 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
38 * Import of OSF Mach kernel (~mburg)
39 *
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]
43 *
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]
47 *
48 * Revision 1.3.8.2 1994/02/11 14:21:41 paire
49 * Added string.h header file for strlen declaration.
50 * [94/02/09 paire]
51 *
52 * Revision 1.3.8.1 1994/02/08 10:57:55 bernadat
53 * Added db_auto_completion variable.
54 * [93/08/17 paire]
55 *
56 * Added support of symbol completion by typing '\t'.
57 * [93/08/14 paire]
58 * [94/02/07 bernadat]
59 *
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]
63 *
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]
67 *
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]
72 *
73 * Added to OSF/1 R1.3 from NMK15.0.
74 * [1993/06/02 20:56:26 jeffc]
75 *
76 * Revision 1.3 1993/04/19 16:02:17 devrcs
77 * Replaced ^R (redraw) with ^L [barbou@gr.osf.org]
78 *
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).
82 * [barbou@gr.osf.org]
83 *
84 * ^C now erases the entire line. [barbou@gr.osf.org]
85 * [92/12/03 bernadat]
86 *
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.
90 * [92/10/02 bernadat]
91 *
92 * Revision 1.2 1992/11/25 01:04:24 robert
93 * integrate changes for norma_14 below
94 *
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]
100 *
101 * integrate changes below for norma_14
102 * [1992/11/13 19:21:34 robert]
103 *
104 * Revision 1.1 1992/09/30 02:01:08 robert
105 * Initial revision
106 *
107 * $EndLog$
108 */
109 /* CMU_HIST */
110 /*
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]
115 *
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]
119 *
120 * Revision 2.8 92/02/19 15:07:44 elf
121 * Added delete_line (Ctrl-U).
122 * [92/02/17 kivinen]
123 *
124 * Added command line history. Ctrl-P = previous, Ctrl-N = next. If
125 * DB_HISTORY_SIZE is 0 then command history is disabled.
126 * [92/02/17 kivinen]
127 *
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.
131 * [91/08/29 tak]
132 *
133 * Revision 2.6.2.1 91/10/05 13:06:12 jeffreyh
134 * Fixed incorrect db_lbuf_end setting.
135 * [91/08/29 tak]
136 *
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.
140 * [91/07/08 danner]
141 *
142 * Revision 2.5 91/05/14 15:34:03 mrt
143 * Correcting copyright
144 *
145 * Revision 2.4 91/02/14 14:41:53 mrt
146 * Add input line editing.
147 * [90/11/11 dbg]
148 *
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]
152 *
153 * Revision 2.2 90/08/27 21:51:03 dbg
154 * Reduce lint.
155 * [90/08/07 dbg]
156 * Created.
157 * [90/07/25 dbg]
158 *
159 */
160 /* CMU_ENDHIST */
161 /*
162 * Mach Operating System
163 * Copyright (c) 1991,1990 Carnegie Mellon University
164 * All Rights Reserved.
165 *
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.
171 *
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.
175 *
176 * Carnegie Mellon requests users of this software to return to
177 *
178 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
179 * School of Computer Science
180 * Carnegie Mellon University
181 * Pittsburgh PA 15213-3890
182 *
183 * any improvements or extensions that they make and grant Carnegie Mellon
184 * the rights to redistribute these changes.
185 */
186 /*
187 */
188 /*
189 * Author: David B. Golub, Carnegie Mellon University
190 * Date: 7/90
191 */
192
193 #include <string.h>
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>
202
203 #ifndef DB_HISTORY_SIZE
204 #define DB_HISTORY_SIZE 4000
205 #endif /* DB_HISTORY_SIZE */
206
207 /*
208 * Character input and editing.
209 */
210
211 /*
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.
215 */
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 */
232 #endif
233
234 #define CTRL(c) ((c) & 0x1f)
235 #define isspace(c) ((c) == ' ' || (c) == '\t')
236 #define BLANK ' '
237 #define BACKUP '\b'
238
239
240
241 /* Prototypes for functions local to this file. XXX -- should be static!
242 */
243 void db_putstring(
244 char *s,
245 int count);
246
247 void db_putnchars(
248 int c,
249 int count);
250
251 void db_delete(
252 int n,
253 int bwd);
254
255 void db_delete_line(void);
256
257 boolean_t db_hist_substring(
258 char *string,
259 char *substring);
260
261 boolean_t db_inputchar(int c);
262
263 extern jmp_buf_t *db_recover;
264
265 void
266 db_putstring(
267 char *s,
268 int count)
269 {
270 while (--count >= 0)
271 cnputc(*s++);
272 }
273
274 void
275 db_putnchars(
276 int c,
277 int count)
278 {
279 while (--count >= 0)
280 cnputc(c);
281 }
282
283 /*
284 * Delete N characters, forward or backward
285 */
286 #define DEL_FWD 0
287 #define DEL_BWD 1
288 void
289 db_delete(
290 int n,
291 int bwd)
292 {
293 register char *p;
294
295 if (bwd) {
296 db_lc -= n;
297 db_putnchars(BACKUP, n);
298 }
299 for (p = db_lc; p < db_le-n; p++) {
300 *p = *(p+n);
301 cnputc(*p);
302 }
303 db_putnchars(BLANK, n);
304 db_putnchars(BACKUP, db_le - db_lc);
305 db_le -= n;
306 }
307
308 void
309 db_delete_line(void)
310 {
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;
314 }
315
316 #if DB_HISTORY_SIZE != 0
317 #define INC_DB_CURR() \
318 do { \
319 db_history_curr++; \
320 if (db_history_curr > \
321 db_history + db_history_size - 1) \
322 db_history_curr = db_history; \
323 } while (0)
324 #define DEC_DB_CURR() \
325 do { \
326 db_history_curr--; \
327 if (db_history_curr < db_history) \
328 db_history_curr = db_history + \
329 db_history_size - 1; \
330 } while (0)
331 #endif
332
333 /* returs TRUE if "substring" is a substring of "string" */
334 boolean_t
335 db_hist_substring(
336 char *string,
337 char *substring)
338 {
339 register char *cp1, *cp2;
340
341 cp1 = string;
342 while (*cp1)
343 cp1++;
344 cp2 = substring;
345 while (*cp2)
346 cp2++;
347
348 while (cp2 > substring) {
349 cp1--; cp2--;
350 }
351
352 while (cp1 >= string) {
353 register char *cp3;
354
355 cp2 = substring;
356 cp3 = cp1;
357 while (*cp2 && *cp2 == *cp3) {
358 cp2++; cp3++;
359 }
360 if (*cp2 == '\0') {
361 return TRUE;
362 }
363 cp1--;
364 }
365 return FALSE;
366 }
367
368 /* returns TRUE at end-of-line */
369 boolean_t
370 db_inputchar(int c)
371 {
372 char *sym;
373 char *start;
374 char *restart;
375 jmp_buf_t db_jmpbuf;
376 jmp_buf_t *db_prev;
377 char *p;
378 int len;
379
380 switch(db_completion) {
381 case -1:
382 db_putchar('\n');
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;
388 db_completion = 0;
389 db_reset_more();
390 db_output_prompt();
391 if (db_le > db_lbuf_start) {
392 for (start = db_lbuf_start; start < db_le; start++)
393 db_putchar(*start);
394 db_putnchars(BACKUP, db_le - db_lc);
395 }
396 return(FALSE);
397
398 case 0:
399 break;
400
401 default:
402 if (c == '\t') {
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();
406 db_completion = -1;
407 db_reset_more();
408 return(FALSE);
409 }
410 db_completion = 0;
411 break;
412 }
413
414 switch (c) {
415 case '\t':
416 /* symbol completion */
417 if (db_lc == db_lbuf_start || db_auto_completion == 0)
418 break;
419 if (db_le == db_lbuf_end) {
420 cnputc('\007');
421 break;
422 }
423 start = db_lc - 1;
424 while (start >= db_lbuf_start &&
425 ((*start >= 'A' && *start <= 'Z') ||
426 (*start >= 'a' && *start <= 'z') ||
427 (*start >= '0' && *start <= '9') ||
428 *start == '_' || *start == ':'))
429 start--;
430 if (start == db_lc - 1)
431 break;
432 if (start > db_lbuf_start && *start == '$') {
433 cnputc('\007');
434 break;
435 }
436 sym = db_tok_string;
437 restart = ++start;
438 do {
439 *sym++ = *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)) {
443 cnputc('\007');
444 break;
445 }
446 *sym = '\0';
447 db_completion = db_lookup_incomplete(db_tok_string,
448 sizeof(db_tok_string));
449 if (db_completion == 0) {
450 /* symbol unknown */
451 cnputc('\007');
452 break;
453 }
454
455 len = strlen(db_tok_string) - (start - restart);
456 if (db_completion == 1 &&
457 (db_le == db_lc ||
458 (db_le > db_lc) && *db_lc != ' '))
459 len++;
460 for (p = db_le - 1; p >= db_lc; p--)
461 *(p + len) = *p;
462 db_le += len;
463 for (sym = &db_tok_string[start - restart];
464 *sym != '\0'; sym++)
465 *db_lc++ = *sym;
466
467 if (db_completion == 1 || db_completion > db_auto_completion) {
468 for (sym = &db_tok_string[start - restart];
469 *sym != '\0'; sym++)
470 cnputc(*sym);
471 if (db_completion == 1) {
472 if (db_le == db_lc ||
473 (db_le > db_lc) && *db_lc != ' ') {
474 cnputc(' ');
475 *db_lc++ = ' ';
476 }
477 db_completion = 0;
478 }
479 db_putstring(db_lc, db_le - db_lc);
480 db_putnchars(BACKUP, db_le - db_lc);
481 }
482
483 if (db_completion > 1) {
484 cnputc('\007');
485 if (db_completion <= db_auto_completion) {
486 db_putchar('\n');
487 db_print_completion(db_tok_string);
488 db_completion = 0;
489 db_reset_more();
490 db_output_prompt();
491 if (db_le > db_lbuf_start) {
492 for (start = db_lbuf_start; start < db_le; start++)
493 db_putchar(*start);
494 db_putnchars(BACKUP, db_le - db_lc);
495 }
496 }
497 }
498 break;
499
500 case CTRL('b'):
501 /* back up one character */
502 if (db_lc > db_lbuf_start) {
503 cnputc(BACKUP);
504 db_lc--;
505 }
506 break;
507 case CTRL('f'):
508 /* forward one character */
509 if (db_lc < db_le) {
510 cnputc(*db_lc);
511 db_lc++;
512 }
513 break;
514 case CTRL('a'):
515 /* beginning of line */
516 while (db_lc > db_lbuf_start) {
517 cnputc(BACKUP);
518 db_lc--;
519 }
520 break;
521 case CTRL('e'):
522 /* end of line */
523 while (db_lc < db_le) {
524 cnputc(*db_lc);
525 db_lc++;
526 }
527 break;
528 case CTRL('h'):
529 case 0177:
530 /* erase previous character */
531 if (db_lc > db_lbuf_start)
532 db_delete(1, DEL_BWD);
533 break;
534 case CTRL('d'):
535 /* erase next character */
536 if (db_lc < db_le)
537 db_delete(1, DEL_FWD);
538 break;
539 case CTRL('k'):
540 /* delete to end of line */
541 if (db_lc < db_le)
542 db_delete(db_le - db_lc, DEL_FWD);
543 break;
544 case CTRL('u'):
545 /* delete to beginning of line */
546 if (db_lc > db_lbuf_start)
547 db_delete(db_lc - db_lbuf_start, DEL_BWD);
548 break;
549 case CTRL('t'):
550 /* twiddle last 2 characters */
551 if (db_lc >= db_lbuf_start + 2) {
552 c = db_lc[-2];
553 db_lc[-2] = db_lc[-1];
554 db_lc[-1] = c;
555 cnputc(BACKUP);
556 cnputc(BACKUP);
557 cnputc(db_lc[-2]);
558 cnputc(db_lc[-1]);
559 }
560 break;
561 case CTRL('c'):
562 case CTRL('g'):
563 db_delete_line();
564 #if DB_HISTORY_SIZE != 0
565 db_history_curr = db_history_last;
566 if (c == CTRL('g') && db_hist_search) {
567 char *p;
568 for (p = db_hist_search_string, db_le = db_lbuf_start;
569 *p; ) {
570 *db_le++ = *p++;
571 }
572 db_lc = db_le;
573 *db_le = '\0';
574 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
575 }
576 #endif
577 break;
578 #if DB_HISTORY_SIZE != 0
579 case CTRL('r'):
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;
584 cp1 < db_le;
585 cp1++, cp2++)
586 *cp2 = *cp1;
587 *cp2 = '\0';
588 db_hist_search++;
589 }
590 /* FALL THROUGH */
591 case CTRL('p'):
592 {
593 char * old_history_curr = db_history_curr;
594
595 if (db_hist_unmodified++ == 0)
596 db_hist_unmodified++;
597 DEC_DB_CURR();
598 while (db_history_curr != db_history_last) {
599 DEC_DB_CURR();
600 if (*db_history_curr == '\0') {
601 INC_DB_CURR();
602 if (db_hist_search <= 1) {
603 if (*db_history_curr == '\0')
604 cnputc('\007');
605 else
606 DEC_DB_CURR();
607 break;
608 }
609 if (*db_history_curr == '\0') {
610 cnputc('\007');
611 db_history_curr = old_history_curr;
612 DEC_DB_CURR();
613 break;
614 }
615 if (db_history_curr != db_history_last &&
616 db_hist_substring(db_history_curr,
617 db_hist_search_string)) {
618 DEC_DB_CURR();
619 break;
620 }
621 DEC_DB_CURR();
622 }
623 }
624 if (db_history_curr == db_history_last) {
625 cnputc('\007');
626 db_history_curr = old_history_curr;
627 } else {
628 register char *p;
629 INC_DB_CURR();
630 db_delete_line();
631 for (p = db_history_curr, db_le = db_lbuf_start;
632 *p; ) {
633 *db_le++ = *p++;
634 if (p == db_history + db_history_size) {
635 p = db_history;
636 }
637 }
638 db_lc = db_le;
639 *db_le = '\0';
640 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
641 }
642 break;
643 }
644 case CTRL('s'):
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;
649 cp1 < db_le;
650 cp1++, cp2++)
651 *cp2 = *cp1;
652 *cp2 = '\0';
653 db_hist_search++;
654 }
655 /* FALL THROUGH */
656 case CTRL('n'):
657 {
658 char *old_history_curr = db_history_curr;
659
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)
665 break;
666 INC_DB_CURR();
667 if (db_history_curr != db_history_last &&
668 db_hist_substring(db_history_curr,
669 db_hist_search_string)) {
670 DEC_DB_CURR();
671 break;
672 }
673 DEC_DB_CURR();
674 }
675 INC_DB_CURR();
676 }
677 if (db_history_curr != db_history_last) {
678 INC_DB_CURR();
679 if (db_history_curr != db_history_last) {
680 register char *p;
681 db_delete_line();
682 for (p = db_history_curr,
683 db_le = db_lbuf_start; *p;) {
684 *db_le++ = *p++;
685 if (p == db_history +
686 db_history_size) {
687 p = db_history;
688 }
689 }
690 db_lc = db_le;
691 *db_le = '\0';
692 db_putstring(db_lbuf_start,
693 db_le - db_lbuf_start);
694 } else {
695 cnputc('\007');
696 db_history_curr = old_history_curr;
697 }
698 } else {
699 cnputc('\007');
700 db_history_curr = old_history_curr;
701 }
702 break;
703 }
704 #endif
705 /* refresh the command line */
706 case CTRL('l'):
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);
711 }
712 break;
713 case '\n':
714 case '\r':
715 #if DB_HISTORY_SIZE != 0
716 /* Check if it same than previous line */
717 if (db_history_prev) {
718 register char *pp, *pc;
719
720 /* Is it unmodified */
721 for (p = db_history_prev, pc = db_lbuf_start;
722 pc != db_le && *p;) {
723 if (*p != *pc)
724 break;
725 if (++p == db_history + db_history_size) {
726 p = db_history;
727 }
728 if (++pc == db_history + db_history_size) {
729 pc = db_history;
730 }
731 }
732 if (!*p && pc == db_le) {
733 /* Repeted previous line, not saved */
734 db_history_curr = db_history_last;
735 *db_le++ = c;
736 db_hist_search = 0;
737 db_hist_unmodified = 0;
738 return (TRUE);
739 }
740 }
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 +
747 db_history_size) {
748 db_history_last = db_history;
749 }
750 }
751 *db_history_last++ = '\0';
752 }
753 db_history_curr = db_history_last;
754 #endif
755 *db_le++ = c;
756 db_hist_search = 0;
757 db_hist_unmodified = 0;
758 return (TRUE);
759 default:
760 if (db_le == db_lbuf_end) {
761 cnputc('\007');
762 }
763 else if (c >= ' ' && c <= '~') {
764 for (p = db_le; p > db_lc; p--)
765 *p = *(p-1);
766 *db_lc++ = c;
767 db_le++;
768 cnputc(c);
769 db_putstring(db_lc, db_le - db_lc);
770 db_putnchars(BACKUP, db_le - db_lc);
771 }
772 break;
773 }
774 if (db_hist_search)
775 db_hist_search--;
776 if (db_hist_unmodified)
777 db_hist_unmodified--;
778 return (FALSE);
779 }
780
781 int
782 db_readline(
783 char * lstart,
784 int lsize)
785 {
786 db_force_whitespace(); /* synch output position */
787
788 db_lbuf_start = lstart;
789 db_lbuf_end = lstart + lsize - 1;
790 db_lc = lstart;
791 db_le = lstart;
792
793 while (!db_inputchar(cngetc()))
794 continue;
795
796 db_putchar('\n'); /* synch output position */
797
798 *db_le = 0;
799 return (db_le - db_lbuf_start);
800 }
801
802 void
803 db_check_interrupt(void)
804 {
805 register int c;
806
807 c = cnmaygetc();
808 switch (c) {
809 case -1: /* no character */
810 return;
811
812 case CTRL('c'):
813 db_error((char *)0);
814 /*NOTREACHED*/
815
816 case CTRL('s'):
817 do {
818 c = cnmaygetc();
819 if (c == CTRL('c'))
820 db_error((char *)0);
821 } while (c != CTRL('q'));
822 break;
823
824 default:
825 /* drop on floor */
826 break;
827 }
828 }