db_input.c revision 49558
1138569Ssam/* 2170375Ssam * Mach Operating System 3138569Ssam * Copyright (c) 1991,1990 Carnegie Mellon University 4138569Ssam * All Rights Reserved. 5138569Ssam * 6138569Ssam * Permission to use, copy, modify and distribute this software and its 7138569Ssam * documentation is hereby granted, provided that both the copyright 8138569Ssam * notice and this permission notice appear in all copies of the 9138569Ssam * software, derivative works or modified versions, and any portions 10138569Ssam * thereof, and that both notices appear in supporting documentation. 11138569Ssam * 12138569Ssam * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 13138569Ssam * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14138569Ssam * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15138569Ssam * 16138569Ssam * Carnegie Mellon requests users of this software to return to 17138569Ssam * 18138569Ssam * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19138569Ssam * School of Computer Science 20138569Ssam * Carnegie Mellon University 21138569Ssam * Pittsburgh PA 15213-3890 22138569Ssam * 23138569Ssam * any improvements or extensions that they make and grant Carnegie the 24138569Ssam * rights to redistribute these changes. 25138569Ssam * 26138569Ssam * $Id: db_input.c,v 1.24 1999/07/14 10:53:41 yokota Exp $ 27138569Ssam */ 28138569Ssam 29138569Ssam/* 30138569Ssam * Author: David B. Golub, Carnegie Mellon University 31138569Ssam * Date: 7/90 32138569Ssam */ 33138569Ssam 34138569Ssam#include <sys/param.h> 35138569Ssam#include <sys/systm.h> 36237529Sadrian#include <sys/cons.h> 37138569Ssam 38178354Ssam#include <ddb/ddb.h> 39138569Ssam#include <ddb/db_output.h> 40138569Ssam 41138569Ssam/* 42138569Ssam * Character input and editing. 43138569Ssam */ 44138569Ssam 45138569Ssam/* 46138569Ssam * We don't track output position while editing input, 47138569Ssam * since input always ends with a new-line. We just 48138569Ssam * reset the line position at the end. 49138569Ssam */ 50138569Ssamstatic char * db_lbuf_start; /* start of input line buffer */ 51138569Ssamstatic char * db_lbuf_end; /* end of input line buffer */ 52138569Ssamstatic char * db_lc; /* current character */ 53138569Ssamstatic char * db_le; /* one past last character */ 54138569Ssam 55138569Ssam/* 56138569Ssam * Simple input line history support. 57138569Ssam */ 58138569Ssamstatic char db_lhistory[2048]; 59138569Ssamstatic int db_lhistlsize, db_lhistidx, db_lhistcur; 60138569Ssamstatic int db_lhist_nlines; 61138569Ssam 62138569Ssam#define CTRL(c) ((c) & 0x1f) 63138569Ssam#define isspace(c) ((c) == ' ' || (c) == '\t') 64138569Ssam#define BLANK ' ' 65138569Ssam#define BACKUP '\b' 66138569Ssam 67138569Ssamstatic int cnmaygetc __P((void)); 68138569Ssamstatic void db_delete __P((int n, int bwd)); 69138569Ssamstatic int db_inputchar __P((int c)); 70185522Ssamstatic void db_putnchars __P((int c, int count)); 71138569Ssamstatic void db_putstring __P((char *s, int count)); 72138569Ssam 73138569Ssamvoid 74138569Ssamdb_putstring(s, count) 75138569Ssam char *s; 76138569Ssam int count; 77138569Ssam{ 78138569Ssam while (--count >= 0) 79138569Ssam cnputc(*s++); 80138569Ssam} 81138569Ssam 82138569Ssamvoid 83138569Ssamdb_putnchars(c, count) 84138569Ssam int c; 85138569Ssam int count; 86138569Ssam{ 87138569Ssam while (--count >= 0) 88138569Ssam cnputc(c); 89138569Ssam} 90138569Ssam 91138569Ssam/* 92138569Ssam * Delete N characters, forward or backward 93138569Ssam */ 94138569Ssam#define DEL_FWD 0 95138569Ssam#define DEL_BWD 1 96138569Ssamvoid 97138569Ssamdb_delete(n, bwd) 98138569Ssam int n; 99138569Ssam int bwd; 100138569Ssam{ 101138569Ssam register char *p; 102138569Ssam 103138569Ssam if (bwd) { 104138569Ssam db_lc -= n; 105138569Ssam db_putnchars(BACKUP, n); 106138569Ssam } 107138569Ssam for (p = db_lc; p < db_le-n; p++) { 108138569Ssam *p = *(p+n); 109138569Ssam cnputc(*p); 110138569Ssam } 111138569Ssam db_putnchars(BLANK, n); 112138569Ssam db_putnchars(BACKUP, db_le - db_lc); 113144546Ssam db_le -= n; 114138569Ssam} 115138569Ssam 116138569Ssam/* returns TRUE at end-of-line */ 117138569Ssamint 118138569Ssamdb_inputchar(c) 119138569Ssam int c; 120138569Ssam{ 121138569Ssam static int escstate; 122138569Ssam 123138569Ssam if (escstate == 1) { 124138569Ssam /* ESC seen, look for [ or O */ 125138569Ssam if (c == '[' || c == 'O') 126218160Sadrian escstate++; 127218160Sadrian else 128218160Sadrian escstate = 0; /* re-init state machine */ 129218160Sadrian return (0); 130218160Sadrian } else if (escstate == 2) { 131218160Sadrian escstate = 0; 132138569Ssam /* 133218160Sadrian * If a valid cursor key has been found, translate 134227364Sadrian * into an emacs-style control key, and fall through. 135218160Sadrian * Otherwise, drop off. 136218160Sadrian */ 137218160Sadrian switch (c) { 138227364Sadrian case 'A': /* up */ 139218160Sadrian c = CTRL('p'); 140227364Sadrian break; 141227364Sadrian case 'B': /* down */ 142227364Sadrian c = CTRL('n'); 143227364Sadrian break; 144227364Sadrian case 'C': /* right */ 145227364Sadrian c = CTRL('f'); 146227364Sadrian break; 147227364Sadrian case 'D': /* left */ 148227364Sadrian c = CTRL('b'); 149218160Sadrian break; 150218160Sadrian default: 151218160Sadrian return (0); 152138569Ssam } 153144546Ssam } 154138569Ssam 155138569Ssam switch (c) { 156138569Ssam case CTRL('['): 157138569Ssam escstate = 1; 158138569Ssam break; 159138569Ssam case CTRL('b'): 160138569Ssam /* back up one character */ 161138569Ssam if (db_lc > db_lbuf_start) { 162138569Ssam cnputc(BACKUP); 163138569Ssam db_lc--; 164138569Ssam } 165144347Ssam break; 166227364Sadrian case CTRL('f'): 167227364Sadrian /* forward one character */ 168138569Ssam if (db_lc < db_le) { 169138569Ssam cnputc(*db_lc); 170138569Ssam db_lc++; 171165185Ssam } 172138569Ssam break; 173138569Ssam case CTRL('a'): 174138569Ssam /* beginning of line */ 175165185Ssam while (db_lc > db_lbuf_start) { 176165185Ssam cnputc(BACKUP); 177178354Ssam db_lc--; 178178354Ssam } 179178354Ssam break; 180178354Ssam case CTRL('e'): 181138569Ssam /* end of line */ 182138569Ssam while (db_lc < db_le) { 183138569Ssam cnputc(*db_lc); 184138569Ssam db_lc++; 185138569Ssam } 186138569Ssam break; 187138569Ssam case CTRL('h'): 188138569Ssam case 0177: 189138569Ssam /* erase previous character */ 190138569Ssam if (db_lc > db_lbuf_start) 191138569Ssam db_delete(1, DEL_BWD); 192138569Ssam break; 193138569Ssam case CTRL('d'): 194138569Ssam /* erase next character */ 195178354Ssam if (db_lc < db_le) 196138569Ssam db_delete(1, DEL_FWD); 197138569Ssam break; 198138569Ssam case CTRL('k'): 199138569Ssam /* delete to end of line */ 200138569Ssam if (db_lc < db_le) 201178354Ssam db_delete(db_le - db_lc, DEL_FWD); 202178354Ssam break; 203178354Ssam case CTRL('t'): 204138569Ssam /* twiddle last 2 characters */ 205138569Ssam if (db_lc >= db_lbuf_start + 2) { 206138569Ssam c = db_lc[-2]; 207138569Ssam db_lc[-2] = db_lc[-1]; 208138569Ssam db_lc[-1] = c; 209138569Ssam cnputc(BACKUP); 210138569Ssam cnputc(BACKUP); 211138569Ssam cnputc(db_lc[-2]); 212138569Ssam cnputc(db_lc[-1]); 213138569Ssam } 214138569Ssam break; 215178354Ssam case CTRL('r'): 216178354Ssam db_putstring("^R\n", 3); 217178354Ssam redraw: 218138569Ssam if (db_le > db_lbuf_start) { 219138569Ssam db_putstring(db_lbuf_start, db_le - db_lbuf_start); 220138569Ssam db_putnchars(BACKUP, db_le - db_lc); 221138569Ssam } 222138569Ssam break; 223138569Ssam case CTRL('p'): 224138569Ssam /* Make previous history line the active one. */ 225138569Ssam if (db_lhistcur >= 0) { 226138569Ssam bcopy(db_lhistory + db_lhistcur * db_lhistlsize, 227138569Ssam db_lbuf_start, db_lhistlsize); 228138569Ssam db_lhistcur--; 229138569Ssam goto hist_redraw; 230138569Ssam } 231138569Ssam break; 232138569Ssam case CTRL('n'): 233138569Ssam /* Make next history line the active one. */ 234138569Ssam if (db_lhistcur < db_lhistidx - 1) { 235138569Ssam db_lhistcur += 2; 236138569Ssam bcopy(db_lhistory + db_lhistcur * db_lhistlsize, 237138569Ssam db_lbuf_start, db_lhistlsize); 238138569Ssam } else { 239138569Ssam /* 240138569Ssam * ^N through tail of history, reset the 241138569Ssam * buffer to zero length. 242138569Ssam */ 243138569Ssam *db_lbuf_start = '\0'; 244138569Ssam db_lhistcur = db_lhistidx; 245138569Ssam } 246138569Ssam 247138569Ssam hist_redraw: 248138569Ssam db_putnchars(BACKUP, db_le - db_lbuf_start); 249138569Ssam db_putnchars(BLANK, db_le - db_lbuf_start); 250138569Ssam db_putnchars(BACKUP, db_le - db_lbuf_start); 251138569Ssam db_le = index(db_lbuf_start, '\0'); 252138569Ssam if (db_le[-1] == '\r' || db_le[-1] == '\n') 253155477Ssam *--db_le = '\0'; 254138569Ssam db_lc = db_le; 255138569Ssam goto redraw; 256138569Ssam 257138569Ssam case -1: 258138569Ssam /* 259138569Ssam * eek! the console returned eof. 260138569Ssam * probably that means we HAVE no console.. we should try bail 261138569Ssam * XXX 262138569Ssam */ 263138569Ssam c = '\r'; 264138569Ssam case '\n': 265178354Ssam case '\r': 266178354Ssam *db_le++ = c; 267178354Ssam return (1); 268178354Ssam default: 269178354Ssam if (db_le == db_lbuf_end) { 270138569Ssam cnputc('\007'); 271138569Ssam } 272138569Ssam else if (c >= ' ' && c <= '~') { 273138569Ssam register char *p; 274138569Ssam 275138569Ssam for (p = db_le; p > db_lc; p--) 276138569Ssam *p = *(p-1); 277138569Ssam *db_lc++ = c; 278138569Ssam db_le++; 279184347Ssam cnputc(c); 280138569Ssam db_putstring(db_lc, db_le - db_lc); 281138569Ssam db_putnchars(BACKUP, db_le - db_lc); 282138569Ssam } 283178354Ssam break; 284138569Ssam } 285138569Ssam return (0); 286138569Ssam} 287138569Ssam 288138569Ssamint 289138569Ssamcnmaygetc() 290138569Ssam{ 291138569Ssam return (-1); 292138569Ssam} 293138569Ssam 294138569Ssamint 295138569Ssamdb_readline(lstart, lsize) 296138569Ssam char * lstart; 297138569Ssam int lsize; 298138569Ssam{ 299138569Ssam if (lsize != db_lhistlsize) { 300138569Ssam /* 301170530Ssam * (Re)initialize input line history. Throw away any 302170530Ssam * existing history. 303138569Ssam */ 304138569Ssam db_lhist_nlines = sizeof(db_lhistory) / lsize; 305138569Ssam db_lhistlsize = lsize; 306138569Ssam db_lhistidx = -1; 307138569Ssam } 308138569Ssam db_lhistcur = db_lhistidx; 309178354Ssam 310138569Ssam db_force_whitespace(); /* synch output position */ 311138569Ssam 312170530Ssam db_lbuf_start = lstart; 313170530Ssam db_lbuf_end = lstart + lsize; 314170530Ssam db_lc = lstart; 315170530Ssam db_le = lstart; 316170530Ssam 317170530Ssam while (!db_inputchar(cngetc())) 318170530Ssam continue; 319138569Ssam 320138569Ssam db_printf("\n"); /* synch output position */ 321138569Ssam *db_le = 0; 322138569Ssam 323138569Ssam if (db_le - db_lbuf_start > 1) { 324138569Ssam /* Maintain input line history for non-empty lines. */ 325138569Ssam if (++db_lhistidx == db_lhist_nlines) { 326138569Ssam /* Rotate history. */ 327138569Ssam ovbcopy(db_lhistory + db_lhistlsize, db_lhistory, 328138569Ssam db_lhistlsize * (db_lhist_nlines - 1)); 329138569Ssam db_lhistidx--; 330138569Ssam } 331138569Ssam bcopy(lstart, db_lhistory + db_lhistidx * db_lhistlsize, 332138569Ssam db_lhistlsize); 333138569Ssam } 334138569Ssam 335138569Ssam return (db_le - db_lbuf_start); 336138569Ssam} 337138569Ssam 338138569Ssamvoid 339138569Ssamdb_check_interrupt() 340138569Ssam{ 341138569Ssam register int c; 342138569Ssam 343138569Ssam c = cnmaygetc(); 344138569Ssam switch (c) { 345138569Ssam case -1: /* no character */ 346138569Ssam return; 347138569Ssam 348138569Ssam case CTRL('c'): 349138569Ssam db_error((char *)0); 350138569Ssam /*NOTREACHED*/ 351138569Ssam 352178354Ssam case CTRL('s'): 353178354Ssam do { 354178354Ssam c = cnmaygetc(); 355138569Ssam if (c == CTRL('c')) 356178354Ssam db_error((char *)0); 357138569Ssam } while (c != CTRL('q')); 358138569Ssam break; 359138569Ssam 360138569Ssam default: 361138569Ssam /* drop on floor */ 362138569Ssam break; 363138569Ssam } 364138569Ssam} 365138569Ssam 366138569Ssam/* called from kdb_trap in db_interface.c */ 367138569Ssamvoid 368138569Ssamcnpollc (flag) 369138569Ssam int flag; 370138569Ssam{ 371138569Ssam} 372138569Ssam