Subject: kern/4504: Implementation of command line history to ddb
To: None <gnats-bugs@gnats.netbsd.org>
From: None <kivinen@ssh.fi>
List: netbsd-bugs
Date: 11/16/1997 13:06:13
>Number:         4504
>Category:       kern
>Synopsis:       ddb doesn't have command line history (ctrl-p/ctrl-n)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Nov 16 03:20:02 1997
>Last-Modified:
>Originator:     Tero Kivinen
>Organization:
SSH Communications Security Ltd
>Release:        1.2
>Environment:
System: NetBSD taulu.ssh.fi 1.2 NetBSD 1.2 (TAULU) #50: Mon Feb 24 21:40:52 EET 1997 kivinen@taulu.ssh.fi:/usr/src/sys/arch/i386/compile/TAULU i386

>Description:
	There isn't a command line history in ddb. 
>How-To-Repeat:
	Try Ctrl-p or Ctrl-n in the ddb prompt, nothing happens :-)
>Fix:

I implemented command line history to mach 3.0 ddb in 1993 and I
patched that version to Netbsd 1.2 ddb last February. I think this
could be added to default distribution. To enable command line history
add

options         DB_HISTORY_SIZE=4000

to kernel config file (allocate 4000 bytes for command line history).
By default DB_HISTORY_SIZE is 0 which disables the command line
history. 
----------------------------------------------------------------------
*** /sys/ddb/db_input.c.orig	Mon Feb  5 03:57:02 1996
--- /sys/ddb/db_input.c	Mon Feb 17 17:11:24 1997
***************
*** 41,46 ****
--- 41,50 ----
  
  #include <dev/cons.h>
  
+ #ifndef DB_HISTORY_SIZE
+ #define DB_HISTORY_SIZE 0
+ #endif /* DB_HISTORY_SIZE */
+ 
  /*
   * Character input and editing.
   */
***************
*** 54,59 ****
--- 58,71 ----
  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 ****
--- 117,147 ----
  	db_le -= n;
  }
  
+ void
+ db_delete_line()
+ {
+ 	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 ****
--- 192,201 ----
  		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,172 ****
--- 208,264 ----
  		    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) {
***************
*** 176,181 ****
--- 268,311 ----
  		break;
  	    case '\n':
  	    case '\r':
+ #if DB_HISTORY_SIZE != 0
+ 		/* Check if it same than previous line */
+ 		if (db_history_curr == db_history_prev) {
+ 			register char *pp, *pc;
+ 
+ 			/* Is it unmodified */
+ 			for (pp = db_history_prev, pc = db_lbuf_start;
+ 			     pc != db_le && *pp; pp++, pc++) {
+ 				if (*pp != *pc)
+ 				    break;
+ 				if (++pp == db_history + db_history_size) {
+ 					pp = db_history;
+ 				}
+ 				if (++pc == db_history + db_history_size) {
+ 					pc = db_history;
+ 				}
+ 			}
+ 			if (!*pp && pc == db_le) {
+ 				/* Repeted previous line, not saved */
+ 				db_history_curr = db_history_last;
+ 				*db_le++ = c;
+ 				return (TRUE);
+ 			}
+ 		}
+ 		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:
>Audit-Trail:
>Unformatted: