1 /* $OpenBSD: db_input.c,v 1.14 2015/03/14 03:38:46 jsg Exp $ */ 2 /* $NetBSD: db_input.c,v 1.7 1996/02/05 01:57:02 christos Exp $ */ 3 4 /* 5 * Mach Operating System 6 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University 7 * All Rights Reserved. 8 * 9 * Permission to use, copy, modify and distribute this software and its 10 * documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie Mellon 27 * the rights to redistribute these changes. 28 * 29 * Author: David B. Golub, Carnegie Mellon University 30 * Date: 7/90 31 */ 32 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 36 #include <machine/db_machdep.h> 37 38 #include <ddb/db_var.h> 39 #include <ddb/db_output.h> 40 #include <ddb/db_sym.h> 41 #include <ddb/db_extern.h> 42 43 #include <dev/cons.h> 44 45 /* 46 * Character input and editing. 47 */ 48 49 /* 50 * We don't track output position while editing input, 51 * since input always ends with a new-line. We just 52 * reset the line position at the end. 53 */ 54 char * db_lbuf_start; /* start of input line buffer */ 55 char * db_lbuf_end; /* end of input line buffer */ 56 char * db_lc; /* current character */ 57 char * db_le; /* one past last character */ 58 #if DB_HISTORY_SIZE != 0 59 char db_history[DB_HISTORY_SIZE]; /* start of history buffer */ 60 int db_history_size = DB_HISTORY_SIZE;/* size of history buffer */ 61 char * db_history_curr = db_history; /* start of current line */ 62 char * db_history_last = db_history; /* start of last line */ 63 char * db_history_prev = (char *) 0; /* start of previous line */ 64 #endif 65 66 67 #define CTRL(c) ((c) & 0x1f) 68 #define isspace(c) ((c) == ' ' || (c) == '\t') 69 #define BLANK ' ' 70 #define BACKUP '\b' 71 72 void 73 db_putstring(char *s, int count) 74 { 75 while (--count >= 0) 76 cnputc(*s++); 77 } 78 79 void 80 db_putnchars(int c, int count) 81 { 82 while (--count >= 0) 83 cnputc(c); 84 } 85 86 /* 87 * Delete N characters, forward or backward 88 */ 89 #define DEL_FWD 0 90 #define DEL_BWD 1 91 void 92 db_delete(int n, int bwd) 93 { 94 char *p; 95 96 if (bwd) { 97 db_lc -= n; 98 db_putnchars(BACKUP, n); 99 } 100 for (p = db_lc; p < db_le-n; p++) { 101 *p = *(p+n); 102 cnputc(*p); 103 } 104 db_putnchars(BLANK, n); 105 db_putnchars(BACKUP, db_le - db_lc); 106 db_le -= n; 107 } 108 109 void 110 db_delete_line(void) 111 { 112 db_delete(db_le - db_lc, DEL_FWD); 113 db_delete(db_lc - db_lbuf_start, DEL_BWD); 114 db_le = db_lc = db_lbuf_start; 115 } 116 117 #if DB_HISTORY_SIZE != 0 118 #define INC_DB_CURR() \ 119 do { \ 120 db_history_curr++; \ 121 if (db_history_curr > \ 122 db_history + db_history_size - 1) \ 123 db_history_curr = db_history; \ 124 } while (0) 125 #define DEC_DB_CURR() \ 126 do { \ 127 db_history_curr--; \ 128 if (db_history_curr < db_history) \ 129 db_history_curr = db_history + \ 130 db_history_size - 1; \ 131 } while (0) 132 #endif 133 134 /* returns TRUE at end-of-line */ 135 int 136 db_inputchar(int c) 137 { 138 switch (c) { 139 case CTRL('b'): 140 /* back up one character */ 141 if (db_lc > db_lbuf_start) { 142 cnputc(BACKUP); 143 db_lc--; 144 } 145 break; 146 case CTRL('f'): 147 /* forward one character */ 148 if (db_lc < db_le) { 149 cnputc(*db_lc); 150 db_lc++; 151 } 152 break; 153 case CTRL('a'): 154 /* beginning of line */ 155 while (db_lc > db_lbuf_start) { 156 cnputc(BACKUP); 157 db_lc--; 158 } 159 break; 160 case CTRL('e'): 161 /* end of line */ 162 while (db_lc < db_le) { 163 cnputc(*db_lc); 164 db_lc++; 165 } 166 break; 167 case CTRL('w'): 168 /* erase word back */ 169 while (db_lc > db_lbuf_start && db_lc[-1] != BLANK) 170 db_delete(1, DEL_BWD); 171 break; 172 case CTRL('h'): 173 case 0177: 174 /* erase previous character */ 175 if (db_lc > db_lbuf_start) 176 db_delete(1, DEL_BWD); 177 break; 178 case CTRL('d'): 179 /* erase next character */ 180 if (db_lc < db_le) 181 db_delete(1, DEL_FWD); 182 break; 183 case CTRL('k'): 184 /* delete to end of line */ 185 if (db_lc < db_le) 186 db_delete(db_le - db_lc, DEL_FWD); 187 break; 188 case CTRL('u'): 189 /* delete line */ 190 db_delete_line(); 191 break; 192 case CTRL('t'): 193 /* twiddle last 2 characters */ 194 if (db_lc >= db_lbuf_start + 2) { 195 c = db_lc[-2]; 196 db_lc[-2] = db_lc[-1]; 197 db_lc[-1] = c; 198 cnputc(BACKUP); 199 cnputc(BACKUP); 200 cnputc(db_lc[-2]); 201 cnputc(db_lc[-1]); 202 } 203 break; 204 #if DB_HISTORY_SIZE != 0 205 case CTRL('p'): 206 DEC_DB_CURR(); 207 while (db_history_curr != db_history_last) { 208 DEC_DB_CURR(); 209 if (*db_history_curr == '\0') 210 break; 211 } 212 db_delete_line(); 213 if (db_history_curr == db_history_last) { 214 INC_DB_CURR(); 215 db_le = db_lc = db_lbuf_start; 216 } else { 217 char *p; 218 INC_DB_CURR(); 219 for (p = db_history_curr, db_le = db_lbuf_start;*p; ) { 220 *db_le++ = *p++; 221 if (p == db_history + db_history_size) 222 p = db_history; 223 } 224 db_lc = db_le; 225 } 226 db_putstring(db_lbuf_start, db_le - db_lbuf_start); 227 break; 228 case CTRL('n'): 229 while (db_history_curr != db_history_last) { 230 if (*db_history_curr == '\0') 231 break; 232 INC_DB_CURR(); 233 } 234 if (db_history_curr != db_history_last) { 235 INC_DB_CURR(); 236 db_delete_line(); 237 if (db_history_curr != db_history_last) { 238 char *p; 239 for (p = db_history_curr, 240 db_le = db_lbuf_start; *p;) { 241 *db_le++ = *p++; 242 if (p == db_history + db_history_size) 243 p = db_history; 244 } 245 db_lc = db_le; 246 } 247 db_putstring(db_lbuf_start, db_le - db_lbuf_start); 248 } 249 break; 250 #endif 251 case CTRL('r'): 252 db_putstring("^R\n", 3); 253 if (db_le > db_lbuf_start) { 254 db_putstring(db_lbuf_start, db_le - db_lbuf_start); 255 db_putnchars(BACKUP, db_le - db_lc); 256 } 257 break; 258 case '\n': 259 case '\r': 260 #if DB_HISTORY_SIZE != 0 261 /* 262 * Check whether current line is the same 263 * as previous saved line. If it is, don`t 264 * save it. 265 */ 266 if (db_history_curr == db_history_prev) { 267 char *pp, *pc; 268 269 /* 270 * Is it the same? 271 */ 272 for (pp = db_history_prev, pc = db_lbuf_start; 273 pc != db_le && *pp; ) { 274 if (*pp != *pc) 275 break; 276 if (++pp == db_history + db_history_size) 277 pp = db_history; 278 pc++; 279 } 280 if (!*pp && pc == db_le) { 281 /* 282 * Repeated previous line. Don`t save. 283 */ 284 db_history_curr = db_history_last; 285 *db_le++ = c; 286 return TRUE; 287 } 288 } 289 if (db_le != db_lbuf_start) { 290 char *p; 291 db_history_prev = db_history_last; 292 for (p = db_lbuf_start; p != db_le; p++) { 293 *db_history_last++ = *p; 294 if (db_history_last == 295 db_history + db_history_size) 296 db_history_last = db_history; 297 } 298 *db_history_last++ = '\0'; 299 } 300 db_history_curr = db_history_last; 301 #endif 302 *db_le++ = c; 303 return TRUE; 304 default: 305 if (db_le == db_lbuf_end) { 306 cnputc('\007'); 307 } 308 else if (c >= ' ' && c <= '~') { 309 char *p; 310 311 for (p = db_le; p > db_lc; p--) 312 *p = *(p-1); 313 *db_lc++ = c; 314 db_le++; 315 cnputc(c); 316 db_putstring(db_lc, db_le - db_lc); 317 db_putnchars(BACKUP, db_le - db_lc); 318 } 319 break; 320 } 321 return FALSE; 322 } 323 324 int 325 db_readline(char *lstart, int lsize) 326 { 327 db_force_whitespace(); /* synch output position */ 328 329 db_lbuf_start = lstart; 330 db_lbuf_end = lstart + lsize - 1; 331 db_lc = lstart; 332 db_le = lstart; 333 334 while (!db_inputchar(cngetc())) 335 continue; 336 337 db_putchar('\n'); /* synch output position */ 338 339 *db_le = 0; 340 return (db_le - db_lbuf_start); 341 } 342