]> git.saurik.com Git - apple/xnu.git/blame_incremental - osfmk/ddb/db_input.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / osfmk / ddb / db_input.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30/*
31 * @OSF_COPYRIGHT@
32 */
33/*
34 * HISTORY
35 *
36 * Revision 1.1.1.1 1998/09/22 21:05:48 wsanchez
37 * Import of Mac OS X kernel (~semeria)
38 *
39 * Revision 1.1.1.1 1998/03/07 02:26:09 wsanchez
40 * Import of OSF Mach kernel (~mburg)
41 *
42 * Revision 1.3.10.2 1994/09/23 01:19:37 ezf
43 * change marker to not FREE
44 * [1994/09/22 21:10:05 ezf]
45 *
46 * Revision 1.3.10.1 1994/06/11 21:11:48 bolinger
47 * Merge up to NMK17.2.
48 * [1994/06/11 20:01:41 bolinger]
49 *
50 * Revision 1.3.8.2 1994/02/11 14:21:41 paire
51 * Added string.h header file for strlen declaration.
52 * [94/02/09 paire]
53 *
54 * Revision 1.3.8.1 1994/02/08 10:57:55 bernadat
55 * Added db_auto_completion variable.
56 * [93/08/17 paire]
57 *
58 * Added support of symbol completion by typing '\t'.
59 * [93/08/14 paire]
60 * [94/02/07 bernadat]
61 *
62 * Revision 1.3.2.4 1993/08/11 20:37:51 elliston
63 * Add ANSI Prototypes. CR #9523.
64 * [1993/08/11 03:33:21 elliston]
65 *
66 * Revision 1.3.2.3 1993/07/27 18:27:30 elliston
67 * Add ANSI prototypes. CR #9523.
68 * [1993/07/27 18:12:01 elliston]
69 *
70 * Revision 1.3.2.2 1993/06/09 02:20:13 gm
71 * CR9176 - ANSI C violations: trailing tokens on CPP
72 * directives, extra semicolons after decl_ ..., asm keywords
73 * [1993/06/07 18:57:14 jeffc]
74 *
75 * Added to OSF/1 R1.3 from NMK15.0.
76 * [1993/06/02 20:56:26 jeffc]
77 *
78 * Revision 1.3 1993/04/19 16:02:17 devrcs
79 * Replaced ^R (redraw) with ^L [barbou@gr.osf.org]
80 *
81 * Added ^R and ^S commands for history search commands
82 * ^U does not erase end of the line anymore. (only erases
83 * from the beginning of the line to current position).
84 * [barbou@gr.osf.org]
85 *
86 * ^C now erases the entire line. [barbou@gr.osf.org]
87 * [92/12/03 bernadat]
88 *
89 * Fixed history management: Do not store repeated typed
90 * command. Null terminate current command in case it is a
91 * substring of the last command.
92 * [92/10/02 bernadat]
93 *
94 * Revision 1.2 1992/11/25 01:04:24 robert
95 * integrate changes for norma_14 below
96 *
97 * Philippe Bernadat (bernadat) at gr.osf.org 02-Oct-92
98 * Fixed history management: Do not store repeated typed
99 * command. Null terminate current command in case it is a
100 * substring of the last command.
101 * [1992/11/20 00:56:07 robert]
102 *
103 * integrate changes below for norma_14
104 * [1992/11/13 19:21:34 robert]
105 *
106 * Revision 1.1 1992/09/30 02:01:08 robert
107 * Initial revision
108 *
109 * $EndLog$
110 */
111/* CMU_HIST */
112/*
113 * Revision 2.7.3.2 92/09/15 17:14:26 jeffreyh
114 * Fixed history code. (Only one char. out of 2 was checked to
115 * compare to last command)
116 * [barbou@gr.osf.org]
117 *
118 * Revision 2.7.3.1 92/03/03 16:13:30 jeffreyh
119 * Pick up changes from TRUNK
120 * [92/02/26 10:59:36 jeffreyh]
121 *
122 * Revision 2.8 92/02/19 15:07:44 elf
123 * Added delete_line (Ctrl-U).
124 * [92/02/17 kivinen]
125 *
126 * Added command line history. Ctrl-P = previous, Ctrl-N = next. If
127 * DB_HISTORY_SIZE is 0 then command history is disabled.
128 * [92/02/17 kivinen]
129 *
130 * Revision 2.7 91/10/09 16:00:03 af
131 * Revision 2.6.2.1 91/10/05 13:06:12 jeffreyh
132 * Fixed incorrect db_lbuf_end setting.
133 * [91/08/29 tak]
134 *
135 * Revision 2.6.2.1 91/10/05 13:06:12 jeffreyh
136 * Fixed incorrect db_lbuf_end setting.
137 * [91/08/29 tak]
138 *
139 * Revision 2.6 91/07/09 23:15:49 danner
140 * Add include of machine/db_machdep.h to allow machine-specific
141 * overrides via defines.
142 * [91/07/08 danner]
143 *
144 * Revision 2.5 91/05/14 15:34:03 mrt
145 * Correcting copyright
146 *
147 * Revision 2.4 91/02/14 14:41:53 mrt
148 * Add input line editing.
149 * [90/11/11 dbg]
150 *
151 * Revision 2.3 91/02/05 17:06:32 mrt
152 * Changed to new Mach copyright
153 * [91/01/31 16:18:13 mrt]
154 *
155 * Revision 2.2 90/08/27 21:51:03 dbg
156 * Reduce lint.
157 * [90/08/07 dbg]
158 * Created.
159 * [90/07/25 dbg]
160 *
161 */
162/* CMU_ENDHIST */
163/*
164 * Mach Operating System
165 * Copyright (c) 1991,1990 Carnegie Mellon University
166 * All Rights Reserved.
167 *
168 * Permission to use, copy, modify and distribute this software and its
169 * documentation is hereby granted, provided that both the copyright
170 * notice and this permission notice appear in all copies of the
171 * software, derivative works or modified versions, and any portions
172 * thereof, and that both notices appear in supporting documentation.
173 *
174 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
175 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
176 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
177 *
178 * Carnegie Mellon requests users of this software to return to
179 *
180 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
181 * School of Computer Science
182 * Carnegie Mellon University
183 * Pittsburgh PA 15213-3890
184 *
185 * any improvements or extensions that they make and grant Carnegie Mellon
186 * the rights to redistribute these changes.
187 */
188/*
189 */
190/*
191 * Author: David B. Golub, Carnegie Mellon University
192 * Date: 7/90
193 */
194
195#include <string.h>
196#include <mach/boolean.h>
197#include <machine/db_machdep.h>
198#include <kern/misc_protos.h>
199#include <ddb/db_output.h>
200#include <ddb/db_lex.h>
201#include <ddb/db_command.h>
202#include <ddb/db_input.h>
203#include <ddb/db_sym.h>
204
205#ifndef DB_HISTORY_SIZE
206#define DB_HISTORY_SIZE 4000
207#endif /* DB_HISTORY_SIZE */
208
209/*
210 * Character input and editing.
211 */
212
213/*
214 * We don't track output position while editing input,
215 * since input always ends with a new-line. We just
216 * reset the line position at the end.
217 */
218char * db_lbuf_start; /* start of input line buffer */
219char * db_lbuf_end; /* end of input line buffer */
220char * db_lc; /* current character */
221char * db_le; /* one past last character */
222int db_completion; /* number of incomplete symbols matched */
223int db_auto_completion = 10; /* number of line to display without asking */
224#if DB_HISTORY_SIZE != 0
225char db_history[DB_HISTORY_SIZE]; /* start of history buffer */
226int db_history_size = DB_HISTORY_SIZE;/* size of history buffer */
227char * db_history_curr = db_history; /* start of current line */
228char * db_history_last = db_history; /* start of last line */
229char * db_history_prev = (char *) 0; /* start of previous line */
230int db_hist_unmodified = 0; /* unmodified line from history */
231int db_hist_search = 0; /* are we in hist search mode ? */
232char db_hist_search_string[DB_LEX_LINE_SIZE];/* the string to look for */
233int db_hist_ignore_dups = 0; /* don't duplicate commands in hist */
234#endif
235
236#define CTRL(c) ((c) & 0x1f)
237#define isspace(c) ((c) == ' ' || (c) == '\t')
238#define BLANK ' '
239#define BACKUP '\b'
240
241
242
243/* Prototypes for functions local to this file. XXX -- should be static!
244 */
245void db_putstring(
246 char *s,
247 int count);
248
249void db_putnchars(
250 int c,
251 int count);
252
253void db_delete(
254 int n,
255 int bwd);
256
257void db_delete_line(void);
258
259boolean_t db_hist_substring(
260 char *string,
261 char *substring);
262
263boolean_t db_inputchar(int c);
264
265extern jmp_buf_t *db_recover;
266
267void
268db_putstring(
269 char *s,
270 int count)
271{
272 while (--count >= 0)
273 cnputc(*s++);
274}
275
276void
277db_putnchars(
278 int c,
279 int count)
280{
281 while (--count >= 0)
282 cnputc(c);
283}
284
285/*
286 * Delete N characters, forward or backward
287 */
288#define DEL_FWD 0
289#define DEL_BWD 1
290void
291db_delete(
292 int n,
293 int bwd)
294{
295 register char *p;
296
297 if (bwd) {
298 db_lc -= n;
299 db_putnchars(BACKUP, n);
300 }
301 for (p = db_lc; p < db_le-n; p++) {
302 *p = *(p+n);
303 cnputc(*p);
304 }
305 db_putnchars(BLANK, n);
306 db_putnchars(BACKUP, db_le - db_lc);
307 db_le -= n;
308}
309
310void
311db_delete_line(void)
312{
313 db_delete(db_le - db_lc, DEL_FWD);
314 db_delete(db_lc - db_lbuf_start, DEL_BWD);
315 db_le = db_lc = db_lbuf_start;
316}
317
318#if DB_HISTORY_SIZE != 0
319#define INC_DB_CURR() \
320 do { \
321 db_history_curr++; \
322 if (db_history_curr > \
323 db_history + db_history_size - 1) \
324 db_history_curr = db_history; \
325 } while (0)
326#define DEC_DB_CURR() \
327 do { \
328 db_history_curr--; \
329 if (db_history_curr < db_history) \
330 db_history_curr = db_history + \
331 db_history_size - 1; \
332 } while (0)
333#endif
334
335/* returs TRUE if "substring" is a substring of "string" */
336boolean_t
337db_hist_substring(
338 char *string,
339 char *substring)
340{
341 register char *cp1, *cp2;
342
343 cp1 = string;
344 while (*cp1)
345 cp1++;
346 cp2 = substring;
347 while (*cp2)
348 cp2++;
349
350 while (cp2 > substring) {
351 cp1--; cp2--;
352 }
353
354 while (cp1 >= string) {
355 register char *cp3;
356
357 cp2 = substring;
358 cp3 = cp1;
359 while (*cp2 && *cp2 == *cp3) {
360 cp2++; cp3++;
361 }
362 if (*cp2 == '\0') {
363 return TRUE;
364 }
365 cp1--;
366 }
367 return FALSE;
368}
369
370/* returns TRUE at end-of-line */
371boolean_t
372db_inputchar(int c)
373{
374 char *sym;
375 char *start;
376 char *restart;
377 jmp_buf_t db_jmpbuf;
378 jmp_buf_t *db_prev;
379 char *p;
380 int len;
381
382 switch(db_completion) {
383 case -1:
384 db_putchar('\n');
385 db_prev = db_recover;
386 if (_setjmp(db_recover = &db_jmpbuf) == 0 &&
387 (c == 'y' || c == ' ' || c == '\t'))
388 db_print_completion(db_tok_string);
389 db_recover = db_prev;
390 db_completion = 0;
391 db_reset_more();
392 db_output_prompt();
393 if (db_le > db_lbuf_start) {
394 for (start = db_lbuf_start; start < db_le; start++)
395 db_putchar(*start);
396 db_putnchars(BACKUP, db_le - db_lc);
397 }
398 return(FALSE);
399
400 case 0:
401 break;
402
403 default:
404 if (c == '\t') {
405 db_printf("\nThere are %d possibilities. ", db_completion);
406 db_printf("Do you really wish to see them all [n] ? ");
407 db_force_whitespace();
408 db_completion = -1;
409 db_reset_more();
410 return(FALSE);
411 }
412 db_completion = 0;
413 break;
414 }
415
416 switch (c) {
417 case '\t':
418 /* symbol completion */
419 if (db_lc == db_lbuf_start || db_auto_completion == 0)
420 break;
421 if (db_le == db_lbuf_end) {
422 cnputc('\007');
423 break;
424 }
425 start = db_lc - 1;
426 while (start >= db_lbuf_start &&
427 ((*start >= 'A' && *start <= 'Z') ||
428 (*start >= 'a' && *start <= 'z') ||
429 (*start >= '0' && *start <= '9') ||
430 *start == '_' || *start == ':'))
431 start--;
432 if (start == db_lc - 1)
433 break;
434 if (start > db_lbuf_start && *start == '$') {
435 cnputc('\007');
436 break;
437 }
438 sym = db_tok_string;
439 restart = ++start;
440 do {
441 *sym++ = *start++;
442 } while (start != db_lc &&
443 sym != db_tok_string + sizeof(db_tok_string));
444 if (sym == db_tok_string + sizeof(db_tok_string)) {
445 cnputc('\007');
446 break;
447 }
448 *sym = '\0';
449 db_completion = db_lookup_incomplete(db_tok_string,
450 sizeof(db_tok_string));
451 if (db_completion == 0) {
452 /* symbol unknown */
453 cnputc('\007');
454 break;
455 }
456
457 len = strlen(db_tok_string) - (start - restart);
458 if (db_completion == 1 &&
459 (db_le == db_lc ||
460 (db_le > db_lc) && *db_lc != ' '))
461 len++;
462 for (p = db_le - 1; p >= db_lc; p--)
463 *(p + len) = *p;
464 db_le += len;
465 for (sym = &db_tok_string[start - restart];
466 *sym != '\0'; sym++)
467 *db_lc++ = *sym;
468
469 if (db_completion == 1 || db_completion > db_auto_completion) {
470 for (sym = &db_tok_string[start - restart];
471 *sym != '\0'; sym++)
472 cnputc(*sym);
473 if (db_completion == 1) {
474 if (db_le == db_lc ||
475 (db_le > db_lc) && *db_lc != ' ') {
476 cnputc(' ');
477 *db_lc++ = ' ';
478 }
479 db_completion = 0;
480 }
481 db_putstring(db_lc, db_le - db_lc);
482 db_putnchars(BACKUP, db_le - db_lc);
483 }
484
485 if (db_completion > 1) {
486 cnputc('\007');
487 if (db_completion <= db_auto_completion) {
488 db_putchar('\n');
489 db_print_completion(db_tok_string);
490 db_completion = 0;
491 db_reset_more();
492 db_output_prompt();
493 if (db_le > db_lbuf_start) {
494 for (start = db_lbuf_start; start < db_le; start++)
495 db_putchar(*start);
496 db_putnchars(BACKUP, db_le - db_lc);
497 }
498 }
499 }
500 break;
501
502 case CTRL('b'):
503 /* back up one character */
504 if (db_lc > db_lbuf_start) {
505 cnputc(BACKUP);
506 db_lc--;
507 }
508 break;
509 case CTRL('f'):
510 /* forward one character */
511 if (db_lc < db_le) {
512 cnputc(*db_lc);
513 db_lc++;
514 }
515 break;
516 case CTRL('a'):
517 /* beginning of line */
518 while (db_lc > db_lbuf_start) {
519 cnputc(BACKUP);
520 db_lc--;
521 }
522 break;
523 case CTRL('e'):
524 /* end of line */
525 while (db_lc < db_le) {
526 cnputc(*db_lc);
527 db_lc++;
528 }
529 break;
530 case CTRL('h'):
531 case 0177:
532 /* erase previous character */
533 if (db_lc > db_lbuf_start)
534 db_delete(1, DEL_BWD);
535 break;
536 case CTRL('d'):
537 /* erase next character */
538 if (db_lc < db_le)
539 db_delete(1, DEL_FWD);
540 break;
541 case CTRL('k'):
542 /* delete to end of line */
543 if (db_lc < db_le)
544 db_delete(db_le - db_lc, DEL_FWD);
545 break;
546 case CTRL('u'):
547 /* delete to beginning of line */
548 if (db_lc > db_lbuf_start)
549 db_delete(db_lc - db_lbuf_start, DEL_BWD);
550 break;
551 case CTRL('t'):
552 /* twiddle last 2 characters */
553 if (db_lc >= db_lbuf_start + 2) {
554 c = db_lc[-2];
555 db_lc[-2] = db_lc[-1];
556 db_lc[-1] = c;
557 cnputc(BACKUP);
558 cnputc(BACKUP);
559 cnputc(db_lc[-2]);
560 cnputc(db_lc[-1]);
561 }
562 break;
563 case CTRL('c'):
564 case CTRL('g'):
565 db_delete_line();
566#if DB_HISTORY_SIZE != 0
567 db_history_curr = db_history_last;
568 if (c == CTRL('g') && db_hist_search) {
569 char *p;
570 for (p = db_hist_search_string, db_le = db_lbuf_start;
571 *p; ) {
572 *db_le++ = *p++;
573 }
574 db_lc = db_le;
575 *db_le = '\0';
576 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
577 }
578#endif
579 break;
580#if DB_HISTORY_SIZE != 0
581 case CTRL('r'):
582 if (db_hist_search++ == 0) {
583 /* starting an history lookup */
584 register char *cp1, *cp2;
585 for (cp1 = db_lbuf_start, cp2 = db_hist_search_string;
586 cp1 < db_le;
587 cp1++, cp2++)
588 *cp2 = *cp1;
589 *cp2 = '\0';
590 db_hist_search++;
591 }
592 /* FALL THROUGH */
593 case CTRL('p'):
594 {
595 char * old_history_curr = db_history_curr;
596
597 if (db_hist_unmodified++ == 0)
598 db_hist_unmodified++;
599 DEC_DB_CURR();
600 while (db_history_curr != db_history_last) {
601 DEC_DB_CURR();
602 if (*db_history_curr == '\0') {
603 INC_DB_CURR();
604 if (db_hist_search <= 1) {
605 if (*db_history_curr == '\0')
606 cnputc('\007');
607 else
608 DEC_DB_CURR();
609 break;
610 }
611 if (*db_history_curr == '\0') {
612 cnputc('\007');
613 db_history_curr = old_history_curr;
614 DEC_DB_CURR();
615 break;
616 }
617 if (db_history_curr != db_history_last &&
618 db_hist_substring(db_history_curr,
619 db_hist_search_string)) {
620 DEC_DB_CURR();
621 break;
622 }
623 DEC_DB_CURR();
624 }
625 }
626 if (db_history_curr == db_history_last) {
627 cnputc('\007');
628 db_history_curr = old_history_curr;
629 } else {
630 register char *p;
631 INC_DB_CURR();
632 db_delete_line();
633 for (p = db_history_curr, db_le = db_lbuf_start;
634 *p; ) {
635 *db_le++ = *p++;
636 if (p == db_history + db_history_size) {
637 p = db_history;
638 }
639 }
640 db_lc = db_le;
641 *db_le = '\0';
642 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
643 }
644 break;
645 }
646 case CTRL('s'):
647 if (db_hist_search++ == 0) {
648 /* starting an history lookup */
649 register char *cp1, *cp2;
650 for (cp1 = db_lbuf_start, cp2 = db_hist_search_string;
651 cp1 < db_le;
652 cp1++, cp2++)
653 *cp2 = *cp1;
654 *cp2 = '\0';
655 db_hist_search++;
656 }
657 /* FALL THROUGH */
658 case CTRL('n'):
659 {
660 char *old_history_curr = db_history_curr;
661
662 if (db_hist_unmodified++ == 0)
663 db_hist_unmodified++;
664 while (db_history_curr != db_history_last) {
665 if (*db_history_curr == '\0') {
666 if (db_hist_search <= 1)
667 break;
668 INC_DB_CURR();
669 if (db_history_curr != db_history_last &&
670 db_hist_substring(db_history_curr,
671 db_hist_search_string)) {
672 DEC_DB_CURR();
673 break;
674 }
675 DEC_DB_CURR();
676 }
677 INC_DB_CURR();
678 }
679 if (db_history_curr != db_history_last) {
680 INC_DB_CURR();
681 if (db_history_curr != db_history_last) {
682 register char *p;
683 db_delete_line();
684 for (p = db_history_curr,
685 db_le = db_lbuf_start; *p;) {
686 *db_le++ = *p++;
687 if (p == db_history +
688 db_history_size) {
689 p = db_history;
690 }
691 }
692 db_lc = db_le;
693 *db_le = '\0';
694 db_putstring(db_lbuf_start,
695 db_le - db_lbuf_start);
696 } else {
697 cnputc('\007');
698 db_history_curr = old_history_curr;
699 }
700 } else {
701 cnputc('\007');
702 db_history_curr = old_history_curr;
703 }
704 break;
705 }
706#endif
707 /* refresh the command line */
708 case CTRL('l'):
709 db_putstring("^L\n", 3);
710 if (db_le > db_lbuf_start) {
711 db_putstring(db_lbuf_start, db_le - db_lbuf_start);
712 db_putnchars(BACKUP, db_le - db_lc);
713 }
714 break;
715 case '\n':
716 case '\r':
717#if DB_HISTORY_SIZE != 0
718 /* Check if it same than previous line */
719 if (db_history_prev) {
720 register char *pp, *pc;
721
722 /* Is it unmodified */
723 for (p = db_history_prev, pc = db_lbuf_start;
724 pc != db_le && *p;) {
725 if (*p != *pc)
726 break;
727 if (++p == db_history + db_history_size) {
728 p = db_history;
729 }
730 if (++pc == db_history + db_history_size) {
731 pc = db_history;
732 }
733 }
734 if (!*p && pc == db_le) {
735 /* Repeted previous line, not saved */
736 db_history_curr = db_history_last;
737 *db_le++ = c;
738 db_hist_search = 0;
739 db_hist_unmodified = 0;
740 return (TRUE);
741 }
742 }
743 if (db_le != db_lbuf_start &&
744 (db_hist_unmodified == 0 || !db_hist_ignore_dups)) {
745 db_history_prev = db_history_last;
746 for (p = db_lbuf_start; p != db_le; p++) {
747 *db_history_last++ = *p;
748 if (db_history_last == db_history +
749 db_history_size) {
750 db_history_last = db_history;
751 }
752 }
753 *db_history_last++ = '\0';
754 }
755 db_history_curr = db_history_last;
756#endif
757 *db_le++ = c;
758 db_hist_search = 0;
759 db_hist_unmodified = 0;
760 return (TRUE);
761 default:
762 if (db_le == db_lbuf_end) {
763 cnputc('\007');
764 }
765 else if (c >= ' ' && c <= '~') {
766 for (p = db_le; p > db_lc; p--)
767 *p = *(p-1);
768 *db_lc++ = c;
769 db_le++;
770 cnputc(c);
771 db_putstring(db_lc, db_le - db_lc);
772 db_putnchars(BACKUP, db_le - db_lc);
773 }
774 break;
775 }
776 if (db_hist_search)
777 db_hist_search--;
778 if (db_hist_unmodified)
779 db_hist_unmodified--;
780 return (FALSE);
781}
782
783int
784db_readline(
785 char * lstart,
786 int lsize)
787{
788 db_force_whitespace(); /* synch output position */
789
790 db_lbuf_start = lstart;
791 db_lbuf_end = lstart + lsize - 1;
792 db_lc = lstart;
793 db_le = lstart;
794
795 while (!db_inputchar(cngetc()))
796 continue;
797
798 db_putchar('\n'); /* synch output position */
799
800 *db_le = 0;
801 return (db_le - db_lbuf_start);
802}
803
804void
805db_check_interrupt(void)
806{
807 register int c;
808
809 c = cnmaygetc();
810 switch (c) {
811 case -1: /* no character */
812 return;
813
814 case CTRL('c'):
815 db_error((char *)0);
816 /*NOTREACHED*/
817
818 case CTRL('s'):
819 do {
820 c = cnmaygetc();
821 if (c == CTRL('c'))
822 db_error((char *)0);
823 } while (c != CTRL('q'));
824 break;
825
826 default:
827 /* drop on floor */
828 break;
829 }
830}