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