[comp.bugs.4bsd] History doesn't behave as described in csh manual page

tonyb@tektools.UUCP (Tony Birnseth) (12/12/86)

Index: /bin/csh 4.3BSD 

Description:
	The csh manual page declares that history references are relative 
	to the the previous history event specified on a line.
		A history reference may be given without an event specification,
		e.g. `!$'.  In this case the reference is to the previous 
		command unless a previous history reference occurred on the 
		same line in which case this form repeats the previous 
		reference.  Thus `!?foo?^ !$' gives the first and last 
		arguments from the command matching `?foo?'.
	This is not the observed behavior.  !$ always references the the last 
	argument of the *previous* command.

	Additionally, the history command should accept 3 arguments, but only
	accepts 2. 'history -r -f 3'.  The code says it should be invoked as
	'history -rf 3' but that's an unreasonable restriction.

Repeat by:
	% echo this is foo
	this is foo
	% echo this is bar
	this is bar
	% !?foo?^ !$
	this bar	# this should have been 'this foo'

Fix:
	Change the argument count in sh.init.c from 2 to 3.
	Change the point at which the last event is assigned.
	Increment the event counter on errors.
	Do some other fooling around with the event counter
	to compensate for the change.

	Apply the following diffs to sh.c, sh.hist.c and sh.init.c and 
	add '-DTEK_HIST -DTEK_BUGS' to the 'DEFS' in the Makefile.
	The '-DTEK_HIST' will add the functionality described in the 
	man page to csh.  The '-DTEK_BUGS' will include the bug fix
	for the history argument counter.

*** /tmp/,RCSt1027842	Thu Dec 11 17:02:54 1986
--- sh.c	Thu Dec 11 12:05:17 1986
***************
*** 742,748
  				printprompt();
  		}
  		err = 0;
! 
  		/*
  		 * Echo not only on VERBOSE, but also with history expansion.
  		 * If there is a lexical error then we forego history echo.

--- 742,748 -----
  				printprompt();
  		}
  		err = 0;
! #ifdef TEK_HIST
  		/*
  		 * Initialize the last event here so that relative history
  		 * accesses (ie !$ !*) remain relative.
***************
*** 744,749
  		err = 0;
  
  		/*
  		 * Echo not only on VERBOSE, but also with history expansion.
  		 * If there is a lexical error then we forego history echo.
  		 */

--- 744,755 -----
  		err = 0;
  #ifdef TEK_HIST
  		/*
+ 		 * Initialize the last event here so that relative history
+ 		 * accesses (ie !$ !*) remain relative.
+ 		 */
+ 		lastev = eventno;
+ #endif /* TEK_HIST */
+ 		/*
  		 * Echo not only on VERBOSE, but also with history expansion.
  		 * If there is a lexical error then we forego history echo.
  		 */
***************
*** 773,778
  		 * Print lexical error messages, except when sourcing
  		 * history lists.
  		 */
  		if (!enterhist && err)
  			error(err);
  

--- 779,785 -----
  		 * Print lexical error messages, except when sourcing
  		 * history lists.
  		 */
+ #ifdef TEK_HIST
  		if (!enterhist && err)
  			/*
  			 * It would be nice if we could bury eventno++ in
***************
*** 774,780
  		 * history lists.
  		 */
  		if (!enterhist && err)
! 			error(err);
  
  		/*
  		 * If had a history command :p modifier then

--- 781,793 -----
  		 */
  #ifdef TEK_HIST
  		if (!enterhist && err)
! 			/*
! 			 * It would be nice if we could bury eventno++ in
! 			 * error().  
! 			 * To many "uninteresting events" use error() to 
! 			 * jump back here.
! 			 */
! 			eventno++, error(err);
  
  		/*
  		 * If had a history command :p modifier then
***************
*** 781,786
  		 * this is as far as we should go
  		 */
  		if (justpr)
  			reset();
  
  		alias(&paraml);

--- 794,808 -----
  		 * this is as far as we should go
  		 */
  		if (justpr)
+ 			eventno++, reset();
+ #else /* ! TEK_HIST */
+ 		if (!enterhist && err)
+ 			error(err);
+ 		/*
+ 		 * If had a history command :p modifier then
+ 		 * this is as far as we should go
+ 		 */
+ 		if (justpr)
  			reset();
  #endif /* TEK_HIST */
  		alias(&paraml);
***************
*** 782,788
  		 */
  		if (justpr)
  			reset();
! 
  		alias(&paraml);
  
  		/*

--- 804,810 -----
  		 */
  		if (justpr)
  			reset();
! #endif /* TEK_HIST */
  		alias(&paraml);
  
  		/*
***************
*** 789,794
  		 * Parse the words of the input into a parse tree.
  		 */
  		t = syntax(paraml.next, &paraml, 0);
  		if (err)
  			error(err);
  

--- 811,817 -----
  		 * Parse the words of the input into a parse tree.
  		 */
  		t = syntax(paraml.next, &paraml, 0);
+ #ifndef TEK_HIST
  		if (err)
  			error(err);
  #else /* TEK_HIST */
***************
*** 791,796
  		t = syntax(paraml.next, &paraml, 0);
  		if (err)
  			error(err);
  
  		/*
  		 * Execute the parse tree

--- 814,822 -----
  #ifndef TEK_HIST
  		if (err)
  			error(err);
+ #else /* TEK_HIST */
+ 		if (err)
+ 			eventno++, error(err);
  
  		/*
  		 * Increment the acutal event number here.
***************
*** 792,797
  		if (err)
  			error(err);
  
  		/*
  		 * Execute the parse tree
  		 */

--- 818,833 -----
  		if (err)
  			eventno++, error(err);
  
+ 		/*
+ 		 * Increment the acutal event number here.
+ 		 * If we waited till after execute(), interupted commands
+ 		 * would not get their history counter incremented.
+ 		 * We pad the eventno when savehist() above calls enthist() 
+ 		 * to place the current command in the history list.
+ 		 */
+ 		if ( t && intty && !whyles ) 
+ 			eventno++;
+ #endif /* TEK_HIST */
  		/*
  		 * Execute the parse tree
  		 */
*** /tmp/,RCSt1027857	Thu Dec 11 17:03:12 1986
--- sh.hist.c	Thu Dec 11 12:43:28 1986
***************
*** 44,49
  			hp->Hnext = np->Hnext, hfree(np);
  		else
  			hp = np;
  	(void) enthist(++eventno, sp, 1);
  }
  

--- 44,52 -----
  			hp->Hnext = np->Hnext, hfree(np);
  		else
  			hp = np;
+ #ifdef TEK_HIST
+ 	(void) enthist(eventno + 1, sp, 1);
+ #else
  	(void) enthist(++eventno, sp, 1);
  #endif
  }
***************
*** 45,50
  		else
  			hp = np;
  	(void) enthist(++eventno, sp, 1);
  }
  
  struct Hist *

--- 48,54 -----
  	(void) enthist(eventno + 1, sp, 1);
  #else
  	(void) enthist(++eventno, sp, 1);
+ #endif
  }
  
  struct Hist *
*** /tmp/,RCSt1027862	Thu Dec 11 17:03:14 1986
--- sh.init.c	Thu Dec 11 12:47:00 1986
***************
*** 118,123
  #ifdef VFORK
  	"hashstat",	hashstat,	0,	0,
  #endif
  	"history",	dohist,		0,	2,
  	"if",		doif,		1,	INF,
  	"jobs",		dojobs,		0,	1,

--- 121,129 -----
  #ifdef VFORK
  	"hashstat",	hashstat,	0,	0,
  #endif
+ #ifdef TEK_BUGS
+ 	"history",	dohist,		0,	3,
+ #else /* ! TEK_BUGS */
  	"history",	dohist,		0,	2,
  #endif /* TEK_BUGS */
  	"if",		doif,		1,	INF,
***************
*** 119,124
  	"hashstat",	hashstat,	0,	0,
  #endif
  	"history",	dohist,		0,	2,
  	"if",		doif,		1,	INF,
  	"jobs",		dojobs,		0,	1,
  	"kill",		dokill,		1,	INF,

--- 125,131 -----
  	"history",	dohist,		0,	3,
  #else /* ! TEK_BUGS */
  	"history",	dohist,		0,	2,
+ #endif /* TEK_BUGS */
  	"if",		doif,		1,	INF,
  	"jobs",		dojobs,		0,	1,
  	"kill",		dokill,		1,	INF,