db_input.c revision 49558
18876Srgrimes/* 24Srgrimes * Mach Operating System 34Srgrimes * Copyright (c) 1991,1990 Carnegie Mellon University 44Srgrimes * All Rights Reserved. 58876Srgrimes * 64Srgrimes * Permission to use, copy, modify and distribute this software and its 74Srgrimes * documentation is hereby granted, provided that both the copyright 84Srgrimes * notice and this permission notice appear in all copies of the 94Srgrimes * software, derivative works or modified versions, and any portions 104Srgrimes * thereof, and that both notices appear in supporting documentation. 118876Srgrimes * 128876Srgrimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 134Srgrimes * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 144Srgrimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 158876Srgrimes * 164Srgrimes * Carnegie Mellon requests users of this software to return to 178876Srgrimes * 184Srgrimes * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 194Srgrimes * School of Computer Science 204Srgrimes * Carnegie Mellon University 214Srgrimes * Pittsburgh PA 15213-3890 228876Srgrimes * 234Srgrimes * any improvements or extensions that they make and grant Carnegie the 244Srgrimes * rights to redistribute these changes. 254Srgrimes * 2649558Sphk * $Id: db_input.c,v 1.24 1999/07/14 10:53:41 yokota Exp $ 274Srgrimes */ 28623Srgrimes 294Srgrimes/* 304Srgrimes * Author: David B. Golub, Carnegie Mellon University 314Srgrimes * Date: 7/90 324Srgrimes */ 334Srgrimes 342056Swollman#include <sys/param.h> 352056Swollman#include <sys/systm.h> 3649558Sphk#include <sys/cons.h> 3712734Sbde 382056Swollman#include <ddb/ddb.h> 392056Swollman#include <ddb/db_output.h> 404Srgrimes 414Srgrimes/* 424Srgrimes * Character input and editing. 434Srgrimes */ 444Srgrimes 454Srgrimes/* 464Srgrimes * We don't track output position while editing input, 474Srgrimes * since input always ends with a new-line. We just 484Srgrimes * reset the line position at the end. 494Srgrimes */ 5012720Sphkstatic char * db_lbuf_start; /* start of input line buffer */ 5112720Sphkstatic char * db_lbuf_end; /* end of input line buffer */ 5212720Sphkstatic char * db_lc; /* current character */ 5312720Sphkstatic char * db_le; /* one past last character */ 544Srgrimes 5517495Sjoerg/* 5617495Sjoerg * Simple input line history support. 5717495Sjoerg */ 5831314Sbdestatic char db_lhistory[2048]; 5917495Sjoergstatic int db_lhistlsize, db_lhistidx, db_lhistcur; 6031062Smsmithstatic int db_lhist_nlines; 6117495Sjoerg 624Srgrimes#define CTRL(c) ((c) & 0x1f) 634Srgrimes#define isspace(c) ((c) == ' ' || (c) == '\t') 644Srgrimes#define BLANK ' ' 654Srgrimes#define BACKUP '\b' 664Srgrimes 6712515Sphkstatic int cnmaygetc __P((void)); 6812515Sphkstatic void db_delete __P((int n, int bwd)); 6912515Sphkstatic int db_inputchar __P((int c)); 7012515Sphkstatic void db_putnchars __P((int c, int count)); 7112515Sphkstatic void db_putstring __P((char *s, int count)); 7212473Sbde 734Srgrimesvoid 744Srgrimesdb_putstring(s, count) 754Srgrimes char *s; 764Srgrimes int count; 774Srgrimes{ 784Srgrimes while (--count >= 0) 794Srgrimes cnputc(*s++); 804Srgrimes} 814Srgrimes 824Srgrimesvoid 834Srgrimesdb_putnchars(c, count) 844Srgrimes int c; 854Srgrimes int count; 864Srgrimes{ 874Srgrimes while (--count >= 0) 884Srgrimes cnputc(c); 894Srgrimes} 904Srgrimes 914Srgrimes/* 924Srgrimes * Delete N characters, forward or backward 934Srgrimes */ 944Srgrimes#define DEL_FWD 0 954Srgrimes#define DEL_BWD 1 964Srgrimesvoid 974Srgrimesdb_delete(n, bwd) 984Srgrimes int n; 994Srgrimes int bwd; 1004Srgrimes{ 1014Srgrimes register char *p; 1024Srgrimes 1034Srgrimes if (bwd) { 1044Srgrimes db_lc -= n; 1054Srgrimes db_putnchars(BACKUP, n); 1064Srgrimes } 1074Srgrimes for (p = db_lc; p < db_le-n; p++) { 1084Srgrimes *p = *(p+n); 1094Srgrimes cnputc(*p); 1104Srgrimes } 1114Srgrimes db_putnchars(BLANK, n); 1124Srgrimes db_putnchars(BACKUP, db_le - db_lc); 1134Srgrimes db_le -= n; 1144Srgrimes} 1154Srgrimes 1164Srgrimes/* returns TRUE at end-of-line */ 1174Srgrimesint 1184Srgrimesdb_inputchar(c) 1194Srgrimes int c; 1204Srgrimes{ 12124840Sjoerg static int escstate; 12224840Sjoerg 12324840Sjoerg if (escstate == 1) { 12424840Sjoerg /* ESC seen, look for [ or O */ 12524840Sjoerg if (c == '[' || c == 'O') 12624840Sjoerg escstate++; 12724840Sjoerg else 12824840Sjoerg escstate = 0; /* re-init state machine */ 12924840Sjoerg return (0); 13024840Sjoerg } else if (escstate == 2) { 13124840Sjoerg escstate = 0; 13224840Sjoerg /* 13324840Sjoerg * If a valid cursor key has been found, translate 13424840Sjoerg * into an emacs-style control key, and fall through. 13524840Sjoerg * Otherwise, drop off. 13624840Sjoerg */ 13724840Sjoerg switch (c) { 13824840Sjoerg case 'A': /* up */ 13924840Sjoerg c = CTRL('p'); 14024840Sjoerg break; 14124840Sjoerg case 'B': /* down */ 14224840Sjoerg c = CTRL('n'); 14324840Sjoerg break; 14424840Sjoerg case 'C': /* right */ 14524840Sjoerg c = CTRL('f'); 14624840Sjoerg break; 14724840Sjoerg case 'D': /* left */ 14824840Sjoerg c = CTRL('b'); 14924840Sjoerg break; 15024840Sjoerg default: 15124840Sjoerg return (0); 15224840Sjoerg } 15324840Sjoerg } 15424840Sjoerg 1554Srgrimes switch (c) { 15624840Sjoerg case CTRL('['): 15724840Sjoerg escstate = 1; 15824840Sjoerg break; 1594Srgrimes case CTRL('b'): 1604Srgrimes /* back up one character */ 1614Srgrimes if (db_lc > db_lbuf_start) { 1624Srgrimes cnputc(BACKUP); 1634Srgrimes db_lc--; 1644Srgrimes } 1654Srgrimes break; 1664Srgrimes case CTRL('f'): 1674Srgrimes /* forward one character */ 1684Srgrimes if (db_lc < db_le) { 1694Srgrimes cnputc(*db_lc); 1704Srgrimes db_lc++; 1714Srgrimes } 1724Srgrimes break; 1734Srgrimes case CTRL('a'): 1744Srgrimes /* beginning of line */ 1754Srgrimes while (db_lc > db_lbuf_start) { 1764Srgrimes cnputc(BACKUP); 1774Srgrimes db_lc--; 1784Srgrimes } 1794Srgrimes break; 1804Srgrimes case CTRL('e'): 1814Srgrimes /* end of line */ 1824Srgrimes while (db_lc < db_le) { 1834Srgrimes cnputc(*db_lc); 1844Srgrimes db_lc++; 1854Srgrimes } 1864Srgrimes break; 1874Srgrimes case CTRL('h'): 1884Srgrimes case 0177: 1894Srgrimes /* erase previous character */ 1904Srgrimes if (db_lc > db_lbuf_start) 1914Srgrimes db_delete(1, DEL_BWD); 1924Srgrimes break; 1934Srgrimes case CTRL('d'): 1944Srgrimes /* erase next character */ 1954Srgrimes if (db_lc < db_le) 1964Srgrimes db_delete(1, DEL_FWD); 1974Srgrimes break; 1984Srgrimes case CTRL('k'): 1994Srgrimes /* delete to end of line */ 2004Srgrimes if (db_lc < db_le) 2014Srgrimes db_delete(db_le - db_lc, DEL_FWD); 2024Srgrimes break; 2034Srgrimes case CTRL('t'): 2044Srgrimes /* twiddle last 2 characters */ 2054Srgrimes if (db_lc >= db_lbuf_start + 2) { 2064Srgrimes c = db_lc[-2]; 2074Srgrimes db_lc[-2] = db_lc[-1]; 2084Srgrimes db_lc[-1] = c; 2094Srgrimes cnputc(BACKUP); 2104Srgrimes cnputc(BACKUP); 2114Srgrimes cnputc(db_lc[-2]); 2124Srgrimes cnputc(db_lc[-1]); 2134Srgrimes } 2144Srgrimes break; 2154Srgrimes case CTRL('r'): 2164Srgrimes db_putstring("^R\n", 3); 21717495Sjoerg redraw: 2184Srgrimes if (db_le > db_lbuf_start) { 2194Srgrimes db_putstring(db_lbuf_start, db_le - db_lbuf_start); 2204Srgrimes db_putnchars(BACKUP, db_le - db_lc); 2214Srgrimes } 2224Srgrimes break; 22317495Sjoerg case CTRL('p'): 22417495Sjoerg /* Make previous history line the active one. */ 22517495Sjoerg if (db_lhistcur >= 0) { 22617495Sjoerg bcopy(db_lhistory + db_lhistcur * db_lhistlsize, 22717495Sjoerg db_lbuf_start, db_lhistlsize); 22817495Sjoerg db_lhistcur--; 22917495Sjoerg goto hist_redraw; 23017495Sjoerg } 23117495Sjoerg break; 23217495Sjoerg case CTRL('n'): 23317495Sjoerg /* Make next history line the active one. */ 23417495Sjoerg if (db_lhistcur < db_lhistidx - 1) { 23517495Sjoerg db_lhistcur += 2; 23617495Sjoerg bcopy(db_lhistory + db_lhistcur * db_lhistlsize, 23717495Sjoerg db_lbuf_start, db_lhistlsize); 23817495Sjoerg } else { 23917495Sjoerg /* 24017495Sjoerg * ^N through tail of history, reset the 24117495Sjoerg * buffer to zero length. 24217495Sjoerg */ 24317495Sjoerg *db_lbuf_start = '\0'; 24417495Sjoerg db_lhistcur = db_lhistidx; 24517495Sjoerg } 24617495Sjoerg 24717495Sjoerg hist_redraw: 24817495Sjoerg db_putnchars(BACKUP, db_le - db_lbuf_start); 24917495Sjoerg db_putnchars(BLANK, db_le - db_lbuf_start); 25017495Sjoerg db_putnchars(BACKUP, db_le - db_lbuf_start); 25117495Sjoerg db_le = index(db_lbuf_start, '\0'); 25217495Sjoerg if (db_le[-1] == '\r' || db_le[-1] == '\n') 25317495Sjoerg *--db_le = '\0'; 25417495Sjoerg db_lc = db_le; 25517495Sjoerg goto redraw; 25617495Sjoerg 25719268Sjulian case -1: 25819268Sjulian /* 25919268Sjulian * eek! the console returned eof. 26019268Sjulian * probably that means we HAVE no console.. we should try bail 26119268Sjulian * XXX 26219268Sjulian */ 26319268Sjulian c = '\r'; 2644Srgrimes case '\n': 2654Srgrimes case '\r': 2664Srgrimes *db_le++ = c; 2674Srgrimes return (1); 2684Srgrimes default: 2694Srgrimes if (db_le == db_lbuf_end) { 2704Srgrimes cnputc('\007'); 2714Srgrimes } 2724Srgrimes else if (c >= ' ' && c <= '~') { 2734Srgrimes register char *p; 2744Srgrimes 2754Srgrimes for (p = db_le; p > db_lc; p--) 2764Srgrimes *p = *(p-1); 2774Srgrimes *db_lc++ = c; 2784Srgrimes db_le++; 2794Srgrimes cnputc(c); 2804Srgrimes db_putstring(db_lc, db_le - db_lc); 2814Srgrimes db_putnchars(BACKUP, db_le - db_lc); 2824Srgrimes } 2834Srgrimes break; 2844Srgrimes } 2854Srgrimes return (0); 2864Srgrimes} 2874Srgrimes 2884Srgrimesint 28912473Sbdecnmaygetc() 2902112Swollman{ 2912112Swollman return (-1); 2922112Swollman} 2932112Swollman 2942112Swollmanint 2954Srgrimesdb_readline(lstart, lsize) 2964Srgrimes char * lstart; 2974Srgrimes int lsize; 2984Srgrimes{ 29931314Sbde if (lsize != db_lhistlsize) { 30031314Sbde /* 30131314Sbde * (Re)initialize input line history. Throw away any 30231314Sbde * existing history. 30331314Sbde */ 30431314Sbde db_lhist_nlines = sizeof(db_lhistory) / lsize; 30517495Sjoerg db_lhistlsize = lsize; 30617495Sjoerg db_lhistidx = -1; 30717495Sjoerg } 30817495Sjoerg db_lhistcur = db_lhistidx; 30917495Sjoerg 3104Srgrimes db_force_whitespace(); /* synch output position */ 3114Srgrimes 3124Srgrimes db_lbuf_start = lstart; 3134Srgrimes db_lbuf_end = lstart + lsize; 3144Srgrimes db_lc = lstart; 3154Srgrimes db_le = lstart; 3164Srgrimes 3174Srgrimes while (!db_inputchar(cngetc())) 3184Srgrimes continue; 3194Srgrimes 32015680Sgpalmer db_printf("\n"); /* synch output position */ 32117495Sjoerg *db_le = 0; 3224Srgrimes 32331314Sbde if (db_le - db_lbuf_start > 1) { 32417495Sjoerg /* Maintain input line history for non-empty lines. */ 32531062Smsmith if (++db_lhistidx == db_lhist_nlines) { 32617495Sjoerg /* Rotate history. */ 32717495Sjoerg ovbcopy(db_lhistory + db_lhistlsize, db_lhistory, 32831062Smsmith db_lhistlsize * (db_lhist_nlines - 1)); 32917495Sjoerg db_lhistidx--; 33017495Sjoerg } 33131314Sbde bcopy(lstart, db_lhistory + db_lhistidx * db_lhistlsize, 33217495Sjoerg db_lhistlsize); 33317495Sjoerg } 33417495Sjoerg 3354Srgrimes return (db_le - db_lbuf_start); 3364Srgrimes} 3374Srgrimes 3384Srgrimesvoid 3394Srgrimesdb_check_interrupt() 3404Srgrimes{ 3414Srgrimes register int c; 3424Srgrimes 3434Srgrimes c = cnmaygetc(); 3444Srgrimes switch (c) { 3454Srgrimes case -1: /* no character */ 3464Srgrimes return; 3474Srgrimes 3484Srgrimes case CTRL('c'): 3494Srgrimes db_error((char *)0); 3504Srgrimes /*NOTREACHED*/ 3514Srgrimes 3524Srgrimes case CTRL('s'): 3534Srgrimes do { 3544Srgrimes c = cnmaygetc(); 3554Srgrimes if (c == CTRL('c')) 3564Srgrimes db_error((char *)0); 3574Srgrimes } while (c != CTRL('q')); 3584Srgrimes break; 3594Srgrimes 3604Srgrimes default: 3614Srgrimes /* drop on floor */ 3624Srgrimes break; 3634Srgrimes } 3644Srgrimes} 3654Srgrimes 3664Srgrimes/* called from kdb_trap in db_interface.c */ 367798Swollmanvoid 3684Srgrimescnpollc (flag) 369798Swollman int flag; 3704Srgrimes{ 3718876Srgrimes} 372