xref: /freebsd/sys/ddb/db_input.c (revision 75680b05c6efe55e93b863d2673eb9b36ac5fa6d)
15b81b6b3SRodney W. Grimes /*
25b81b6b3SRodney W. Grimes  * Mach Operating System
35b81b6b3SRodney W. Grimes  * Copyright (c) 1991,1990 Carnegie Mellon University
45b81b6b3SRodney W. Grimes  * All Rights Reserved.
55b81b6b3SRodney W. Grimes  *
65b81b6b3SRodney W. Grimes  * Permission to use, copy, modify and distribute this software and its
75b81b6b3SRodney W. Grimes  * documentation is hereby granted, provided that both the copyright
85b81b6b3SRodney W. Grimes  * notice and this permission notice appear in all copies of the
95b81b6b3SRodney W. Grimes  * software, derivative works or modified versions, and any portions
105b81b6b3SRodney W. Grimes  * thereof, and that both notices appear in supporting documentation.
115b81b6b3SRodney W. Grimes  *
125b81b6b3SRodney W. Grimes  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
135b81b6b3SRodney W. Grimes  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
145b81b6b3SRodney W. Grimes  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
155b81b6b3SRodney W. Grimes  *
165b81b6b3SRodney W. Grimes  * Carnegie Mellon requests users of this software to return to
175b81b6b3SRodney W. Grimes  *
185b81b6b3SRodney W. Grimes  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
195b81b6b3SRodney W. Grimes  *  School of Computer Science
205b81b6b3SRodney W. Grimes  *  Carnegie Mellon University
215b81b6b3SRodney W. Grimes  *  Pittsburgh PA 15213-3890
225b81b6b3SRodney W. Grimes  *
235b81b6b3SRodney W. Grimes  * any improvements or extensions that they make and grant Carnegie the
245b81b6b3SRodney W. Grimes  * rights to redistribute these changes.
250edf66ecSRodney W. Grimes  *
2675680b05SJulian Elischer  *	$Id: db_input.c,v 1.14 1996/08/10 13:38:44 joerg Exp $
275b81b6b3SRodney W. Grimes  */
280edf66ecSRodney W. Grimes 
295b81b6b3SRodney W. Grimes /*
305b81b6b3SRodney W. Grimes  *	Author: David B. Golub, Carnegie Mellon University
315b81b6b3SRodney W. Grimes  *	Date:	7/90
325b81b6b3SRodney W. Grimes  */
335b81b6b3SRodney W. Grimes 
34f540b106SGarrett Wollman #include <sys/param.h>
35b4630773SJoerg Wunsch #include <sys/malloc.h>
36f540b106SGarrett Wollman #include <sys/systm.h>
375ccbc3ccSBruce Evans 
385ccbc3ccSBruce Evans #include <machine/cons.h>
395ccbc3ccSBruce Evans 
40f540b106SGarrett Wollman #include <ddb/ddb.h>
41f540b106SGarrett Wollman #include <ddb/db_output.h>
425b81b6b3SRodney W. Grimes 
435b81b6b3SRodney W. Grimes /*
445b81b6b3SRodney W. Grimes  * Character input and editing.
455b81b6b3SRodney W. Grimes  */
465b81b6b3SRodney W. Grimes 
475b81b6b3SRodney W. Grimes /*
485b81b6b3SRodney W. Grimes  * We don't track output position while editing input,
495b81b6b3SRodney W. Grimes  * since input always ends with a new-line.  We just
505b81b6b3SRodney W. Grimes  * reset the line position at the end.
515b81b6b3SRodney W. Grimes  */
5225eb640dSPoul-Henning Kamp static char *	db_lbuf_start;	/* start of input line buffer */
5325eb640dSPoul-Henning Kamp static char *	db_lbuf_end;	/* end of input line buffer */
5425eb640dSPoul-Henning Kamp static char *	db_lc;		/* current character */
5525eb640dSPoul-Henning Kamp static char *	db_le;		/* one past last character */
565b81b6b3SRodney W. Grimes 
57b4630773SJoerg Wunsch /*
58b4630773SJoerg Wunsch  * Simple input line history support.
59b4630773SJoerg Wunsch  */
60b4630773SJoerg Wunsch static char *	db_lhistory;
61b4630773SJoerg Wunsch static int	db_lhistlsize, db_lhistidx, db_lhistcur;
62b4630773SJoerg Wunsch #define DB_LHIST_NLINES 10
63b4630773SJoerg Wunsch 
645b81b6b3SRodney W. Grimes #define	CTRL(c)		((c) & 0x1f)
655b81b6b3SRodney W. Grimes #define	isspace(c)	((c) == ' ' || (c) == '\t')
665b81b6b3SRodney W. Grimes #define	BLANK		' '
675b81b6b3SRodney W. Grimes #define	BACKUP		'\b'
685b81b6b3SRodney W. Grimes 
69f73a856dSPoul-Henning Kamp static int	cnmaygetc __P((void));
70f73a856dSPoul-Henning Kamp static void	db_delete __P((int n, int bwd));
71f73a856dSPoul-Henning Kamp static int	db_inputchar __P((int c));
72f73a856dSPoul-Henning Kamp static void	db_putnchars __P((int c, int count));
73f73a856dSPoul-Henning Kamp static void	db_putstring __P((char *s, int count));
74058284fcSBruce Evans 
755b81b6b3SRodney W. Grimes void
765b81b6b3SRodney W. Grimes db_putstring(s, count)
775b81b6b3SRodney W. Grimes 	char	*s;
785b81b6b3SRodney W. Grimes 	int	count;
795b81b6b3SRodney W. Grimes {
805b81b6b3SRodney W. Grimes 	while (--count >= 0)
815b81b6b3SRodney W. Grimes 	    cnputc(*s++);
825b81b6b3SRodney W. Grimes }
835b81b6b3SRodney W. Grimes 
845b81b6b3SRodney W. Grimes void
855b81b6b3SRodney W. Grimes db_putnchars(c, count)
865b81b6b3SRodney W. Grimes 	int	c;
875b81b6b3SRodney W. Grimes 	int	count;
885b81b6b3SRodney W. Grimes {
895b81b6b3SRodney W. Grimes 	while (--count >= 0)
905b81b6b3SRodney W. Grimes 	    cnputc(c);
915b81b6b3SRodney W. Grimes }
925b81b6b3SRodney W. Grimes 
935b81b6b3SRodney W. Grimes /*
945b81b6b3SRodney W. Grimes  * Delete N characters, forward or backward
955b81b6b3SRodney W. Grimes  */
965b81b6b3SRodney W. Grimes #define	DEL_FWD		0
975b81b6b3SRodney W. Grimes #define	DEL_BWD		1
985b81b6b3SRodney W. Grimes void
995b81b6b3SRodney W. Grimes db_delete(n, bwd)
1005b81b6b3SRodney W. Grimes 	int	n;
1015b81b6b3SRodney W. Grimes 	int	bwd;
1025b81b6b3SRodney W. Grimes {
1035b81b6b3SRodney W. Grimes 	register char *p;
1045b81b6b3SRodney W. Grimes 
1055b81b6b3SRodney W. Grimes 	if (bwd) {
1065b81b6b3SRodney W. Grimes 	    db_lc -= n;
1075b81b6b3SRodney W. Grimes 	    db_putnchars(BACKUP, n);
1085b81b6b3SRodney W. Grimes 	}
1095b81b6b3SRodney W. Grimes 	for (p = db_lc; p < db_le-n; p++) {
1105b81b6b3SRodney W. Grimes 	    *p = *(p+n);
1115b81b6b3SRodney W. Grimes 	    cnputc(*p);
1125b81b6b3SRodney W. Grimes 	}
1135b81b6b3SRodney W. Grimes 	db_putnchars(BLANK, n);
1145b81b6b3SRodney W. Grimes 	db_putnchars(BACKUP, db_le - db_lc);
1155b81b6b3SRodney W. Grimes 	db_le -= n;
1165b81b6b3SRodney W. Grimes }
1175b81b6b3SRodney W. Grimes 
1185b81b6b3SRodney W. Grimes /* returns TRUE at end-of-line */
1195b81b6b3SRodney W. Grimes int
1205b81b6b3SRodney W. Grimes db_inputchar(c)
1215b81b6b3SRodney W. Grimes 	int	c;
1225b81b6b3SRodney W. Grimes {
1235b81b6b3SRodney W. Grimes 	switch (c) {
1245b81b6b3SRodney W. Grimes 	    case CTRL('b'):
1255b81b6b3SRodney W. Grimes 		/* back up one character */
1265b81b6b3SRodney W. Grimes 		if (db_lc > db_lbuf_start) {
1275b81b6b3SRodney W. Grimes 		    cnputc(BACKUP);
1285b81b6b3SRodney W. Grimes 		    db_lc--;
1295b81b6b3SRodney W. Grimes 		}
1305b81b6b3SRodney W. Grimes 		break;
1315b81b6b3SRodney W. Grimes 	    case CTRL('f'):
1325b81b6b3SRodney W. Grimes 		/* forward one character */
1335b81b6b3SRodney W. Grimes 		if (db_lc < db_le) {
1345b81b6b3SRodney W. Grimes 		    cnputc(*db_lc);
1355b81b6b3SRodney W. Grimes 		    db_lc++;
1365b81b6b3SRodney W. Grimes 		}
1375b81b6b3SRodney W. Grimes 		break;
1385b81b6b3SRodney W. Grimes 	    case CTRL('a'):
1395b81b6b3SRodney W. Grimes 		/* beginning of line */
1405b81b6b3SRodney W. Grimes 		while (db_lc > db_lbuf_start) {
1415b81b6b3SRodney W. Grimes 		    cnputc(BACKUP);
1425b81b6b3SRodney W. Grimes 		    db_lc--;
1435b81b6b3SRodney W. Grimes 		}
1445b81b6b3SRodney W. Grimes 		break;
1455b81b6b3SRodney W. Grimes 	    case CTRL('e'):
1465b81b6b3SRodney W. Grimes 		/* end of line */
1475b81b6b3SRodney W. Grimes 		while (db_lc < db_le) {
1485b81b6b3SRodney W. Grimes 		    cnputc(*db_lc);
1495b81b6b3SRodney W. Grimes 		    db_lc++;
1505b81b6b3SRodney W. Grimes 		}
1515b81b6b3SRodney W. Grimes 		break;
1525b81b6b3SRodney W. Grimes 	    case CTRL('h'):
1535b81b6b3SRodney W. Grimes 	    case 0177:
1545b81b6b3SRodney W. Grimes 		/* erase previous character */
1555b81b6b3SRodney W. Grimes 		if (db_lc > db_lbuf_start)
1565b81b6b3SRodney W. Grimes 		    db_delete(1, DEL_BWD);
1575b81b6b3SRodney W. Grimes 		break;
1585b81b6b3SRodney W. Grimes 	    case CTRL('d'):
1595b81b6b3SRodney W. Grimes 		/* erase next character */
1605b81b6b3SRodney W. Grimes 		if (db_lc < db_le)
1615b81b6b3SRodney W. Grimes 		    db_delete(1, DEL_FWD);
1625b81b6b3SRodney W. Grimes 		break;
1635b81b6b3SRodney W. Grimes 	    case CTRL('k'):
1645b81b6b3SRodney W. Grimes 		/* delete to end of line */
1655b81b6b3SRodney W. Grimes 		if (db_lc < db_le)
1665b81b6b3SRodney W. Grimes 		    db_delete(db_le - db_lc, DEL_FWD);
1675b81b6b3SRodney W. Grimes 		break;
1685b81b6b3SRodney W. Grimes 	    case CTRL('t'):
1695b81b6b3SRodney W. Grimes 		/* twiddle last 2 characters */
1705b81b6b3SRodney W. Grimes 		if (db_lc >= db_lbuf_start + 2) {
1715b81b6b3SRodney W. Grimes 		    c = db_lc[-2];
1725b81b6b3SRodney W. Grimes 		    db_lc[-2] = db_lc[-1];
1735b81b6b3SRodney W. Grimes 		    db_lc[-1] = c;
1745b81b6b3SRodney W. Grimes 		    cnputc(BACKUP);
1755b81b6b3SRodney W. Grimes 		    cnputc(BACKUP);
1765b81b6b3SRodney W. Grimes 		    cnputc(db_lc[-2]);
1775b81b6b3SRodney W. Grimes 		    cnputc(db_lc[-1]);
1785b81b6b3SRodney W. Grimes 		}
1795b81b6b3SRodney W. Grimes 		break;
1805b81b6b3SRodney W. Grimes 	    case CTRL('r'):
1815b81b6b3SRodney W. Grimes 		db_putstring("^R\n", 3);
182b4630773SJoerg Wunsch 	    redraw:
1835b81b6b3SRodney W. Grimes 		if (db_le > db_lbuf_start) {
1845b81b6b3SRodney W. Grimes 		    db_putstring(db_lbuf_start, db_le - db_lbuf_start);
1855b81b6b3SRodney W. Grimes 		    db_putnchars(BACKUP, db_le - db_lc);
1865b81b6b3SRodney W. Grimes 		}
1875b81b6b3SRodney W. Grimes 		break;
188b4630773SJoerg Wunsch 	    case CTRL('p'):
189b4630773SJoerg Wunsch 		/* Make previous history line the active one. */
190b4630773SJoerg Wunsch 		if (db_lhistcur >= 0) {
191b4630773SJoerg Wunsch 		    bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
192b4630773SJoerg Wunsch 			  db_lbuf_start, db_lhistlsize);
193b4630773SJoerg Wunsch 		    db_lhistcur--;
194b4630773SJoerg Wunsch 		    goto hist_redraw;
195b4630773SJoerg Wunsch 		}
196b4630773SJoerg Wunsch 		break;
197b4630773SJoerg Wunsch 	    case CTRL('n'):
198b4630773SJoerg Wunsch 		/* Make next history line the active one. */
199b4630773SJoerg Wunsch 		if (db_lhistcur < db_lhistidx - 1) {
200b4630773SJoerg Wunsch 		    db_lhistcur += 2;
201b4630773SJoerg Wunsch 		    bcopy(db_lhistory + db_lhistcur * db_lhistlsize,
202b4630773SJoerg Wunsch 			  db_lbuf_start, db_lhistlsize);
203b4630773SJoerg Wunsch 		} else {
204b4630773SJoerg Wunsch 		    /*
205b4630773SJoerg Wunsch 		     * ^N through tail of history, reset the
206b4630773SJoerg Wunsch 		     * buffer to zero length.
207b4630773SJoerg Wunsch 		     */
208b4630773SJoerg Wunsch 		    *db_lbuf_start = '\0';
209b4630773SJoerg Wunsch 		    db_lhistcur = db_lhistidx;
210b4630773SJoerg Wunsch 		}
211b4630773SJoerg Wunsch 
212b4630773SJoerg Wunsch 	    hist_redraw:
213b4630773SJoerg Wunsch 		db_putnchars(BACKUP, db_le - db_lbuf_start);
214b4630773SJoerg Wunsch 		db_putnchars(BLANK, db_le - db_lbuf_start);
215b4630773SJoerg Wunsch 		db_putnchars(BACKUP, db_le - db_lbuf_start);
216b4630773SJoerg Wunsch 		db_le = index(db_lbuf_start, '\0');
217b4630773SJoerg Wunsch 		if (db_le[-1] == '\r' || db_le[-1] == '\n')
218b4630773SJoerg Wunsch 		    *--db_le = '\0';
219b4630773SJoerg Wunsch 		db_lc = db_le;
220b4630773SJoerg Wunsch 		goto redraw;
221b4630773SJoerg Wunsch 
22275680b05SJulian Elischer 	    case -1:
22375680b05SJulian Elischer 		/*
22475680b05SJulian Elischer 		 * eek! the console returned eof.
22575680b05SJulian Elischer 		 * probably that means we HAVE no console.. we should try bail
22675680b05SJulian Elischer 		 * XXX
22775680b05SJulian Elischer 		 */
22875680b05SJulian Elischer 		c = '\r';
2295b81b6b3SRodney W. Grimes 	    case '\n':
2305b81b6b3SRodney W. Grimes 	    case '\r':
2315b81b6b3SRodney W. Grimes 		*db_le++ = c;
2325b81b6b3SRodney W. Grimes 		return (1);
2335b81b6b3SRodney W. Grimes 	    default:
2345b81b6b3SRodney W. Grimes 		if (db_le == db_lbuf_end) {
2355b81b6b3SRodney W. Grimes 		    cnputc('\007');
2365b81b6b3SRodney W. Grimes 		}
2375b81b6b3SRodney W. Grimes 		else if (c >= ' ' && c <= '~') {
2385b81b6b3SRodney W. Grimes 		    register char *p;
2395b81b6b3SRodney W. Grimes 
2405b81b6b3SRodney W. Grimes 		    for (p = db_le; p > db_lc; p--)
2415b81b6b3SRodney W. Grimes 			*p = *(p-1);
2425b81b6b3SRodney W. Grimes 		    *db_lc++ = c;
2435b81b6b3SRodney W. Grimes 		    db_le++;
2445b81b6b3SRodney W. Grimes 		    cnputc(c);
2455b81b6b3SRodney W. Grimes 		    db_putstring(db_lc, db_le - db_lc);
2465b81b6b3SRodney W. Grimes 		    db_putnchars(BACKUP, db_le - db_lc);
2475b81b6b3SRodney W. Grimes 		}
2485b81b6b3SRodney W. Grimes 		break;
2495b81b6b3SRodney W. Grimes 	}
2505b81b6b3SRodney W. Grimes 	return (0);
2515b81b6b3SRodney W. Grimes }
2525b81b6b3SRodney W. Grimes 
2535b81b6b3SRodney W. Grimes int
254058284fcSBruce Evans cnmaygetc()
255f23b4c91SGarrett Wollman {
256f23b4c91SGarrett Wollman 	return (-1);
257f23b4c91SGarrett Wollman }
258f23b4c91SGarrett Wollman 
259f23b4c91SGarrett Wollman int
2605b81b6b3SRodney W. Grimes db_readline(lstart, lsize)
2615b81b6b3SRodney W. Grimes 	char *	lstart;
2625b81b6b3SRodney W. Grimes 	int	lsize;
2635b81b6b3SRodney W. Grimes {
264b4630773SJoerg Wunsch 	if (db_lhistory && lsize != db_lhistlsize) {
265b4630773SJoerg Wunsch 		/* Should not happen, but to be sane, throw history away. */
266b4630773SJoerg Wunsch 		FREE(db_lhistory, M_TEMP);
267b4630773SJoerg Wunsch 		db_lhistory = 0;
268b4630773SJoerg Wunsch 	}
269b4630773SJoerg Wunsch 	if (db_lhistory == 0) {
270b4630773SJoerg Wunsch 		/* Initialize input line history. */
271b4630773SJoerg Wunsch 		db_lhistlsize = lsize;
272b4630773SJoerg Wunsch 		db_lhistidx = -1;
273b4630773SJoerg Wunsch 		MALLOC(db_lhistory, char *, lsize * DB_LHIST_NLINES,
274b4630773SJoerg Wunsch 		       M_TEMP, M_NOWAIT);
275b4630773SJoerg Wunsch 	}
276b4630773SJoerg Wunsch 	db_lhistcur = db_lhistidx;
277b4630773SJoerg Wunsch 
2785b81b6b3SRodney W. Grimes 	db_force_whitespace();	/* synch output position */
2795b81b6b3SRodney W. Grimes 
2805b81b6b3SRodney W. Grimes 	db_lbuf_start = lstart;
2815b81b6b3SRodney W. Grimes 	db_lbuf_end   = lstart + lsize;
2825b81b6b3SRodney W. Grimes 	db_lc = lstart;
2835b81b6b3SRodney W. Grimes 	db_le = lstart;
2845b81b6b3SRodney W. Grimes 
2855b81b6b3SRodney W. Grimes 	while (!db_inputchar(cngetc()))
2865b81b6b3SRodney W. Grimes 	    continue;
2875b81b6b3SRodney W. Grimes 
2886ddbf1e2SGary Palmer 	db_printf("\n");	/* synch output position */
2895b81b6b3SRodney W. Grimes 	*db_le = 0;
290b4630773SJoerg Wunsch 
291b4630773SJoerg Wunsch 	if (db_le - db_lbuf_start > 1) {
292b4630773SJoerg Wunsch 	    /* Maintain input line history for non-empty lines. */
293b4630773SJoerg Wunsch 	    if (++db_lhistidx == DB_LHIST_NLINES) {
294b4630773SJoerg Wunsch 		/* Rotate history. */
295b4630773SJoerg Wunsch 		ovbcopy(db_lhistory + db_lhistlsize, db_lhistory,
296b4630773SJoerg Wunsch 			db_lhistlsize * (DB_LHIST_NLINES - 1));
297b4630773SJoerg Wunsch 		db_lhistidx--;
298b4630773SJoerg Wunsch 	    }
299b4630773SJoerg Wunsch 	    bcopy(lstart, db_lhistory + (db_lhistidx * db_lhistlsize),
300b4630773SJoerg Wunsch 		  db_lhistlsize);
301b4630773SJoerg Wunsch 	}
302b4630773SJoerg Wunsch 
3035b81b6b3SRodney W. Grimes 	return (db_le - db_lbuf_start);
3045b81b6b3SRodney W. Grimes }
3055b81b6b3SRodney W. Grimes 
3065b81b6b3SRodney W. Grimes void
3075b81b6b3SRodney W. Grimes db_check_interrupt()
3085b81b6b3SRodney W. Grimes {
3095b81b6b3SRodney W. Grimes 	register int	c;
3105b81b6b3SRodney W. Grimes 
3115b81b6b3SRodney W. Grimes 	c = cnmaygetc();
3125b81b6b3SRodney W. Grimes 	switch (c) {
3135b81b6b3SRodney W. Grimes 	    case -1:		/* no character */
3145b81b6b3SRodney W. Grimes 		return;
3155b81b6b3SRodney W. Grimes 
3165b81b6b3SRodney W. Grimes 	    case CTRL('c'):
3175b81b6b3SRodney W. Grimes 		db_error((char *)0);
3185b81b6b3SRodney W. Grimes 		/*NOTREACHED*/
3195b81b6b3SRodney W. Grimes 
3205b81b6b3SRodney W. Grimes 	    case CTRL('s'):
3215b81b6b3SRodney W. Grimes 		do {
3225b81b6b3SRodney W. Grimes 		    c = cnmaygetc();
3235b81b6b3SRodney W. Grimes 		    if (c == CTRL('c'))
3245b81b6b3SRodney W. Grimes 			db_error((char *)0);
3255b81b6b3SRodney W. Grimes 		} while (c != CTRL('q'));
3265b81b6b3SRodney W. Grimes 		break;
3275b81b6b3SRodney W. Grimes 
3285b81b6b3SRodney W. Grimes 	    default:
3295b81b6b3SRodney W. Grimes 		/* drop on floor */
3305b81b6b3SRodney W. Grimes 		break;
3315b81b6b3SRodney W. Grimes 	}
3325b81b6b3SRodney W. Grimes }
3335b81b6b3SRodney W. Grimes 
3345b81b6b3SRodney W. Grimes /* called from kdb_trap in db_interface.c */
335381fe1aaSGarrett Wollman void
3365b81b6b3SRodney W. Grimes cnpollc (flag)
337381fe1aaSGarrett Wollman 	int flag;
3385b81b6b3SRodney W. Grimes {
3395b81b6b3SRodney W. Grimes }
340