1/* 2 * Copyright (c) 2000-2005 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 */ 216char * db_lbuf_start; /* start of input line buffer */ 217char * db_lbuf_end; /* end of input line buffer */ 218char * db_lc; /* current character */ 219char * db_le; /* one past last character */ 220int db_completion; /* number of incomplete symbols matched */ 221int db_auto_completion = 10; /* number of line to display without asking */ 222#if DB_HISTORY_SIZE != 0 223char db_history[DB_HISTORY_SIZE]; /* start of history buffer */ 224int db_history_size = DB_HISTORY_SIZE;/* size of history buffer */ 225char * db_history_curr = db_history; /* start of current line */ 226char * db_history_last = db_history; /* start of last line */ 227char * db_history_prev = (char *) 0; /* start of previous line */ 228int db_hist_unmodified = 0; /* unmodified line from history */ 229int db_hist_search = 0; /* are we in hist search mode ? */ 230char db_hist_search_string[DB_LEX_LINE_SIZE];/* the string to look for */ 231int 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 */ 243void db_putstring(const char *s, int count); 244 245void db_putnchars( 246 int c, 247 int count); 248 249void db_delete( 250 int n, 251 int bwd); 252 253void db_delete_line(void); 254 255boolean_t db_hist_substring( 256 char *string, 257 char *substring); 258 259boolean_t db_inputchar(int c); 260 261extern jmp_buf_t *db_recover; 262 263void 264db_putstring(const char *s, int count) 265{ 266 while (--count >= 0) 267 cnputc(*s++); 268} 269 270void 271db_putnchars( 272 int c, 273 int count) 274{ 275 while (--count >= 0) 276 cnputc(c); 277} 278 279/* 280 * Delete N characters, forward or backward 281 */ 282#define DEL_FWD 0 283#define DEL_BWD 1 284void 285db_delete( 286 int n, 287 int bwd) 288{ 289 register char *p; 290 291 if (bwd) { 292 db_lc -= n; 293 db_putnchars(BACKUP, n); 294 } 295 for (p = db_lc; p < db_le-n; p++) { 296 *p = *(p+n); 297 cnputc(*p); 298 } 299 db_putnchars(BLANK, n); 300 db_putnchars(BACKUP, db_le - db_lc); 301 db_le -= n; 302} 303 304void 305db_delete_line(void) 306{ 307 db_delete(db_le - db_lc, DEL_FWD); 308 db_delete(db_lc - db_lbuf_start, DEL_BWD); 309 db_le = db_lc = db_lbuf_start; 310} 311 312#if DB_HISTORY_SIZE != 0 313#define INC_DB_CURR() \ 314 do { \ 315 db_history_curr++; \ 316 if (db_history_curr > \ 317 db_history + db_history_size - 1) \ 318 db_history_curr = db_history; \ 319 } while (0) 320#define DEC_DB_CURR() \ 321 do { \ 322 db_history_curr--; \ 323 if (db_history_curr < db_history) \ 324 db_history_curr = db_history + \ 325 db_history_size - 1; \ 326 } while (0) 327#endif 328 329/* returs TRUE if "substring" is a substring of "string" */ 330boolean_t 331db_hist_substring( 332 char *string, 333 char *substring) 334{ 335 register char *cp1, *cp2; 336 337 cp1 = string; 338 while (*cp1) 339 cp1++; 340 cp2 = substring; 341 while (*cp2) 342 cp2++; 343 344 while (cp2 > substring) { 345 cp1--; cp2--; 346 } 347 348 while (cp1 >= string) { 349 register char *cp3; 350 351 cp2 = substring; 352 cp3 = cp1; 353 while (*cp2 && *cp2 == *cp3) { 354 cp2++; cp3++; 355 } 356 if (*cp2 == '\0') { 357 return TRUE; 358 } 359 cp1--; 360 } 361 return FALSE; 362} 363 364/* returns TRUE at end-of-line */ 365boolean_t 366db_inputchar(int c) 367{ 368 char *sym; 369 char *start; 370 char *restart; 371 jmp_buf_t db_jmpbuf; 372 jmp_buf_t *local_prev; 373 char *p; 374 int len; 375 376 switch(db_completion) { 377 case -1: 378 db_putchar('\n'); 379 local_prev = db_recover; 380 if (_setjmp(db_recover = &db_jmpbuf) == 0 && 381 (c == 'y' || c == ' ' || c == '\t')) 382 db_print_completion(db_tok_string); 383 db_recover = local_prev; 384 db_completion = 0; 385 db_reset_more(); 386 db_output_prompt(); 387 if (db_le > db_lbuf_start) { 388 for (start = db_lbuf_start; start < db_le; start++) 389 db_putchar(*start); 390 db_putnchars(BACKUP, db_le - db_lc); 391 } 392 return(FALSE); 393 394 case 0: 395 break; 396 397 default: 398 if (c == '\t') { 399 db_printf("\nThere are %d possibilities. ", db_completion); 400 db_printf("Do you really wish to see them all [n] ? "); 401 db_force_whitespace(); 402 db_completion = -1; 403 db_reset_more(); 404 return(FALSE); 405 } 406 db_completion = 0; 407 break; 408 } 409 410 switch (c) { 411 case '\t': 412 /* symbol completion */ 413 if (db_lc == db_lbuf_start || db_auto_completion == 0) 414 break; 415 if (db_le == db_lbuf_end) { 416 cnputc('\007'); 417 break; 418 } 419 start = db_lc - 1; 420 while (start >= db_lbuf_start && 421 ((*start >= 'A' && *start <= 'Z') || 422 (*start >= 'a' && *start <= 'z') || 423 (*start >= '0' && *start <= '9') || 424 *start == '_' || *start == ':')) 425 start--; 426 if (start == db_lc - 1) 427 break; 428 if (start > db_lbuf_start && *start == '$') { 429 cnputc('\007'); 430 break; 431 } 432 sym = db_tok_string; 433 restart = ++start; 434 do { 435 *sym++ = *start++; 436 } while (start != db_lc && 437 sym != db_tok_string + sizeof(db_tok_string)); 438 if (sym == db_tok_string + sizeof(db_tok_string)) { 439 cnputc('\007'); 440 break; 441 } 442 *sym = '\0'; 443 db_completion = db_lookup_incomplete(db_tok_string, 444 sizeof(db_tok_string)); 445 if (db_completion == 0) { 446 /* symbol unknown */ 447 cnputc('\007'); 448 break; 449 } 450 451 len = strlen(db_tok_string) - (start - restart); 452 if (db_completion == 1 && 453 (db_le == db_lc || 454 ((db_le > db_lc) && *db_lc != ' '))) 455 len++; 456 for (p = db_le - 1; p >= db_lc; p--) 457 *(p + len) = *p; 458 db_le += len; 459 for (sym = &db_tok_string[start - restart]; 460 *sym != '\0'; sym++) 461 *db_lc++ = *sym; 462 463 if (db_completion == 1 || db_completion > db_auto_completion) { 464 for (sym = &db_tok_string[start - restart]; 465 *sym != '\0'; sym++) 466 cnputc(*sym); 467 if (db_completion == 1) { 468 if (db_le == db_lc || 469 ((db_le > db_lc) && *db_lc != ' ')) { 470 cnputc(' '); 471 *db_lc++ = ' '; 472 } 473 db_completion = 0; 474 } 475 db_putstring(db_lc, db_le - db_lc); 476 db_putnchars(BACKUP, db_le - db_lc); 477 } 478 479 if (db_completion > 1) { 480 cnputc('\007'); 481 if (db_completion <= db_auto_completion) { 482 db_putchar('\n'); 483 db_print_completion(db_tok_string); 484 db_completion = 0; 485 db_reset_more(); 486 db_output_prompt(); 487 if (db_le > db_lbuf_start) { 488 for (start = db_lbuf_start; start < db_le; start++) 489 db_putchar(*start); 490 db_putnchars(BACKUP, db_le - db_lc); 491 } 492 } 493 } 494 break; 495 496 case CTRL('b'): 497 /* back up one character */ 498 if (db_lc > db_lbuf_start) { 499 cnputc(BACKUP); 500 db_lc--; 501 } 502 break; 503 case CTRL('f'): 504 /* forward one character */ 505 if (db_lc < db_le) { 506 cnputc(*db_lc); 507 db_lc++; 508 } 509 break; 510 case CTRL('a'): 511 /* beginning of line */ 512 while (db_lc > db_lbuf_start) { 513 cnputc(BACKUP); 514 db_lc--; 515 } 516 break; 517 case CTRL('e'): 518 /* end of line */ 519 while (db_lc < db_le) { 520 cnputc(*db_lc); 521 db_lc++; 522 } 523 break; 524 case CTRL('h'): 525 case 0177: 526 /* erase previous character */ 527 if (db_lc > db_lbuf_start) 528 db_delete(1, DEL_BWD); 529 break; 530 case CTRL('d'): 531 /* erase next character */ 532 if (db_lc < db_le) 533 db_delete(1, DEL_FWD); 534 break; 535 case CTRL('k'): 536 /* delete to end of line */ 537 if (db_lc < db_le) 538 db_delete(db_le - db_lc, DEL_FWD); 539 break; 540 case CTRL('u'): 541 /* delete to beginning of line */ 542 if (db_lc > db_lbuf_start) 543 db_delete(db_lc - db_lbuf_start, DEL_BWD); 544 break; 545 case CTRL('t'): 546 /* twiddle last 2 characters */ 547 if (db_lc >= db_lbuf_start + 2) { 548 c = db_lc[-2]; 549 db_lc[-2] = db_lc[-1]; 550 db_lc[-1] = c; 551 cnputc(BACKUP); 552 cnputc(BACKUP); 553 cnputc(db_lc[-2]); 554 cnputc(db_lc[-1]); 555 } 556 break; 557 case CTRL('c'): 558 case CTRL('g'): 559 db_delete_line(); 560#if DB_HISTORY_SIZE != 0 561 db_history_curr = db_history_last; 562 if (c == CTRL('g') && db_hist_search) { 563 for (p = db_hist_search_string, db_le = db_lbuf_start; 564 *p; ) { 565 *db_le++ = *p++; 566 } 567 db_lc = db_le; 568 *db_le = '\0'; 569 db_putstring(db_lbuf_start, db_le - db_lbuf_start); 570 } 571#endif 572 break; 573#if DB_HISTORY_SIZE != 0 574 case CTRL('r'): 575 if (db_hist_search++ == 0) { 576 /* starting an history lookup */ 577 register char *cp1, *cp2; 578 for (cp1 = db_lbuf_start, cp2 = db_hist_search_string; 579 cp1 < db_le; 580 cp1++, cp2++) 581 *cp2 = *cp1; 582 *cp2 = '\0'; 583 db_hist_search++; 584 } 585 /* FALL THROUGH */ 586 case CTRL('p'): 587 { 588 char * old_history_curr = db_history_curr; 589 590 if (db_hist_unmodified++ == 0) 591 db_hist_unmodified++; 592 DEC_DB_CURR(); 593 while (db_history_curr != db_history_last) { 594 DEC_DB_CURR(); 595 if (*db_history_curr == '\0') { 596 INC_DB_CURR(); 597 if (db_hist_search <= 1) { 598 if (*db_history_curr == '\0') 599 cnputc('\007'); 600 else 601 DEC_DB_CURR(); 602 break; 603 } 604 if (*db_history_curr == '\0') { 605 cnputc('\007'); 606 db_history_curr = old_history_curr; 607 DEC_DB_CURR(); 608 break; 609 } 610 if (db_history_curr != db_history_last && 611 db_hist_substring(db_history_curr, 612 db_hist_search_string)) { 613 DEC_DB_CURR(); 614 break; 615 } 616 DEC_DB_CURR(); 617 } 618 } 619 if (db_history_curr == db_history_last) { 620 cnputc('\007'); 621 db_history_curr = old_history_curr; 622 } else { 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 db_delete_line(); 675 for (p = db_history_curr, 676 db_le = db_lbuf_start; *p;) { 677 *db_le++ = *p++; 678 if (p == db_history + 679 db_history_size) { 680 p = db_history; 681 } 682 } 683 db_lc = db_le; 684 *db_le = '\0'; 685 db_putstring(db_lbuf_start, 686 db_le - db_lbuf_start); 687 } else { 688 cnputc('\007'); 689 db_history_curr = old_history_curr; 690 } 691 } else { 692 cnputc('\007'); 693 db_history_curr = old_history_curr; 694 } 695 break; 696 } 697#endif 698 /* refresh the command line */ 699 case CTRL('l'): 700 db_putstring("^L\n", 3); 701 if (db_le > db_lbuf_start) { 702 db_putstring(db_lbuf_start, db_le - db_lbuf_start); 703 db_putnchars(BACKUP, db_le - db_lc); 704 } 705 break; 706 case '\n': 707 case '\r': 708#if DB_HISTORY_SIZE != 0 709 /* Check if it same than previous line */ 710 if (db_history_prev) { 711 char *pc; 712 713 /* Is it unmodified */ 714 for (p = db_history_prev, pc = db_lbuf_start; 715 pc != db_le && *p;) { 716 if (*p != *pc) 717 break; 718 if (++p == db_history + db_history_size) { 719 p = db_history; 720 } 721 if (++pc == db_history + db_history_size) { 722 pc = db_history; 723 } 724 } 725 if (!*p && pc == db_le) { 726 /* Repeted previous line, not saved */ 727 db_history_curr = db_history_last; 728 *db_le++ = c; 729 db_hist_search = 0; 730 db_hist_unmodified = 0; 731 return (TRUE); 732 } 733 } 734 if (db_le != db_lbuf_start && 735 (db_hist_unmodified == 0 || !db_hist_ignore_dups)) { 736 db_history_prev = db_history_last; 737 for (p = db_lbuf_start; p != db_le; p++) { 738 *db_history_last++ = *p; 739 if (db_history_last == db_history + 740 db_history_size) { 741 db_history_last = db_history; 742 } 743 } 744 *db_history_last++ = '\0'; 745 } 746 db_history_curr = db_history_last; 747#endif 748 *db_le++ = c; 749 db_hist_search = 0; 750 db_hist_unmodified = 0; 751 return (TRUE); 752 default: 753 if (db_le == db_lbuf_end) { 754 cnputc('\007'); 755 } 756 else if (c >= ' ' && c <= '~') { 757 for (p = db_le; p > db_lc; p--) 758 *p = *(p-1); 759 *db_lc++ = c; 760 db_le++; 761 cnputc(c); 762 db_putstring(db_lc, db_le - db_lc); 763 db_putnchars(BACKUP, db_le - db_lc); 764 } 765 break; 766 } 767 if (db_hist_search) 768 db_hist_search--; 769 if (db_hist_unmodified) 770 db_hist_unmodified--; 771 return (FALSE); 772} 773 774int 775db_readline( 776 char * lstart, 777 int lsize) 778{ 779 db_force_whitespace(); /* synch output position */ 780 781 db_lbuf_start = lstart; 782 db_lbuf_end = lstart + lsize - 1; 783 db_lc = lstart; 784 db_le = lstart; 785 786 while (!db_inputchar(cngetc())) 787 continue; 788 789 db_putchar('\n'); /* synch output position */ 790 791 *db_le = 0; 792 return (db_le - db_lbuf_start); 793} 794 795void 796db_check_interrupt(void) 797{ 798 register int c; 799 800 c = cnmaygetc(); 801 switch (c) { 802 case -1: /* no character */ 803 return; 804 805 case CTRL('c'): 806 db_error((char *)0); 807 /*NOTREACHED*/ 808 809 case CTRL('s'): 810 do { 811 c = cnmaygetc(); 812 if (c == CTRL('c')) 813 db_error((char *)0); 814 } while (c != CTRL('q')); 815 break; 816 817 default: 818 /* drop on floor */ 819 break; 820 } 821} 822