Subject: kernel debugger patch ...
To: None <port-i386@NetBSD.ORG>
From: Robert.V.Baron <rvb@gluck.coda.cs.cmu.edu>
List: port-i386
Date: 01/10/1998 20:56:00
I've been reapplying some of my local changes of NetBSD 1.2 into NetBSD
1.3.  I noticed that I've had a patch that enables ^n and ^p for the
kernel debugger.  I've submitted a "bug report" with the change, but I
thought I'd also just include the patch here since people might want
the change and it sometimes takes a while for code to get into -current.

Added command line history. Ctrl-P = previous, Ctrl-N = next. If
DB_HISTORY_SIZE is 0 then command history is disabled.
[92/02/17            kivinen]

Index: src/sys/ddb/db_extern.h
diff -c src/sys/ddb/db_extern.h:1.1.1.1 src/sys/ddb/db_extern.h:1.2
*** src/sys/ddb/db_extern.h:1.1.1.1	Thu Jun 26 07:22:45 1997
--- src/sys/ddb/db_extern.h	Sat Jan 10 05:52:36 1998
***************
*** 68,73 ****
--- 68,74 ----
  void db_putstring __P((char *, int));
  void db_putnchars __P((int, int));
  void db_delete __P((int, int));
+ void db_delete_line __P((void));
  int db_inputchar __P((int));
  int db_readline __P((char *, int));
  void db_check_interrupt __P((void));
Index: src/sys/ddb/db_input.c
diff -c src/sys/ddb/db_input.c:1.1.1.1 src/sys/ddb/db_input.c:1.2
*** src/sys/ddb/db_input.c:1.1.1.1	Mon Feb  5 07:25:34 1996
--- src/sys/ddb/db_input.c	Sat Jan 10 05:52:37 1998
***************
*** 45,50 ****
--- 45,54 ----
   * Character input and editing.
   */
  
+ #ifndef DB_HISTORY_SIZE
+ #define DB_HISTORY_SIZE 4000
+ #endif DB_HISTORY_SIZE
+ 
  /*
   * We don't track output position while editing input,
   * since input always ends with a new-line.  We just
***************
*** 54,59 ****
--- 58,70 ----
  char *	db_lbuf_end;	/* end of input line buffer */
  char *	db_lc;		/* current character */
  char *	db_le;		/* one past last character */
+ #if DB_HISTORY_SIZE != 0
+ char    db_history[DB_HISTORY_SIZE];	/* start of history buffer */
+ int     db_history_size = DB_HISTORY_SIZE;/* size of history buffer */
+ char *  db_history_curr = db_history;	/* start of current line */
+ char *  db_history_last = db_history;	/* start of last line */
+ char *  db_history_prev = (char *) 0;	/* start of previous line */
+ #endif
  
  #define	CTRL(c)		((c) & 0x1f)
  #define	isspace(c)	((c) == ' ' || (c) == '\t')
***************
*** 105,110 ****
--- 116,146 ----
  	db_le -= n;
  }
  
+ void
+ db_delete_line(void)
+ {
+ 	db_delete(db_le - db_lc, DEL_FWD);
+ 	db_delete(db_lc - db_lbuf_start, DEL_BWD);
+ 	db_le = db_lc = db_lbuf_start;
+ }
+ 
+ #if DB_HISTORY_SIZE != 0
+ #define INC_DB_CURR() \
+     do { \
+ 	     db_history_curr++; \
+ 	     if (db_history_curr > \
+ 		 db_history + db_history_size - 1) \
+ 		     db_history_curr = db_history; \
+        } while (0)
+ #define DEC_DB_CURR() \
+     do { \
+ 	     db_history_curr--; \
+ 	     if (db_history_curr < db_history) \
+ 		 db_history_curr = db_history + \
+ 		 db_history_size - 1; \
+        } while (0)
+ #endif
+ 
  /* returns TRUE at end-of-line */
  int
  db_inputchar(c)
***************
*** 155,160 ****
--- 191,200 ----
  		if (db_lc < db_le)
  		    db_delete(db_le - db_lc, DEL_FWD);
  		break;
+ 	    case CTRL('u'):
+ 		/* delete line */
+ 	        db_delete_line();
+ 		break;
  	    case CTRL('t'):
  		/* twiddle last 2 characters */
  		if (db_lc >= db_lbuf_start + 2) {
***************
*** 167,181 ****
  		    cnputc(db_lc[-1]);
  		}
  		break;
  	    case CTRL('r'):
  		db_putstring("^R\n", 3);
  		if (db_le > db_lbuf_start) {
! 		    db_putstring(db_lbuf_start, db_le - db_lbuf_start);
! 		    db_putnchars(BACKUP, db_le - db_lc);
  		}
  		break;
  	    case '\n':
  	    case '\r':
  		*db_le++ = c;
  		return (1);
  	    default:
--- 207,316 ----
  		    cnputc(db_lc[-1]);
  		}
  		break;
+ #if DB_HISTORY_SIZE != 0
+ 	    case CTRL('p'):
+ 	        DEC_DB_CURR();
+ 	        while (db_history_curr != db_history_last) {
+ 			DEC_DB_CURR();
+ 			if (*db_history_curr == '\0')
+ 			    break;
+ 		}
+ 		db_delete_line();
+ 		if (db_history_curr == db_history_last) {
+ 			INC_DB_CURR();
+ 			db_le = db_lc = db_lbuf_start;
+ 		} else {
+ 			register char *p;
+ 			INC_DB_CURR();
+ 			for (p = db_history_curr, db_le = db_lbuf_start;
+ 			     *p; ) {
+ 				*db_le++ = *p++;
+ 				if (p == db_history + db_history_size) {
+ 					p = db_history;
+ 				}
+ 			}
+ 			db_lc = db_le;
+ 		}
+ 		db_putstring(db_lbuf_start, db_le - db_lbuf_start);
+ 		break;
+ 	    case CTRL('n'):
+ 	        while (db_history_curr != db_history_last) {
+ 			if (*db_history_curr == '\0')
+ 			    break;
+ 			INC_DB_CURR();
+ 		}
+ 		if (db_history_curr != db_history_last) {
+ 			INC_DB_CURR();
+ 			db_delete_line();
+ 			if (db_history_curr != db_history_last) {
+ 				register char *p;
+ 				for (p = db_history_curr,
+ 				     db_le = db_lbuf_start; *p;) {
+ 					*db_le++ = *p++;
+ 					if (p == db_history +
+ 					    db_history_size) {
+ 						p = db_history;
+ 					}
+ 				}
+ 				db_lc = db_le;
+ 			}
+ 			db_putstring(db_lbuf_start, db_le - db_lbuf_start);
+ 		}
+ 		break;
+ #endif
  	    case CTRL('r'):
  		db_putstring("^R\n", 3);
  		if (db_le > db_lbuf_start) {
! 			db_putstring(db_lbuf_start, db_le - db_lbuf_start);
! 			db_putnchars(BACKUP, db_le - db_lc);
  		}
  		break;
  	    case '\n':
  	    case '\r':
+ #if DB_HISTORY_SIZE != 0
+ 		/*
+ 		 * Check whether current line is the same
+ 		 * as previous saved line.  If it is, don`t
+ 		 * save it.
+ 		 */
+ 		if (db_history_curr == db_history_prev) {
+ 			register char *pp, *pc;
+ 
+ 			/*
+ 			 * Is it the same?
+ 			 */
+ 			for (pp = db_history_prev, pc = db_lbuf_start;
+ 			     pc != db_le && *pp; ) {
+ 				if (*pp != *pc)
+ 				    break;
+ 				if (++pp == db_history + db_history_size) {
+ 					pp = db_history;
+ 				}
+ 				pc++;
+ 			}
+ 			if (!*pp && pc == db_le) {
+ 				/*
+ 				 * Repeated previous line. Don`t save.
+ 				 */
+ 				db_history_curr = db_history_last;
+ 				*db_le++ = c;
+ 				return (1);
+ 			}
+ 		}
+ 		if (db_le != db_lbuf_start) {
+ 			register char *p;
+ 			db_history_prev = db_history_last;
+ 			for (p = db_lbuf_start; p != db_le; p++) {
+ 				*db_history_last++ = *p;
+ 				if (db_history_last == db_history +
+ 				    db_history_size) {
+ 					db_history_last = db_history;
+ 				}
+ 			}
+ 			*db_history_last++ = '\0';
+ 		}
+ 		db_history_curr = db_history_last;
+ #endif
  		*db_le++ = c;
  		return (1);
  	    default:
***************
*** 206,212 ****
  	db_force_whitespace();	/* synch output position */
  
  	db_lbuf_start = lstart;
! 	db_lbuf_end   = lstart + lsize;
  	db_lc = lstart;
  	db_le = lstart;
  
--- 341,347 ----
  	db_force_whitespace();	/* synch output position */
  
  	db_lbuf_start = lstart;
! 	db_lbuf_end   = lstart + lsize - 1;
  	db_lc = lstart;
  	db_le = lstart;