Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: 3.0-pre6 expansion bug



jfblank@xxxxxxx wrote:
> I first noticed this in 2.6b13...
> 
> bullwinkle<275>:Src/zsh -f
> bullwinkle% cat ~/file
> [...]
> bullwinkle% <!$<TAB>
> correctly expands to
> bullwinkle% <~/file
> [...]
> bullwinkle% less<!$
> incorrectly expands to
> bullwinkle% less~/.zlogin
> 
> Then, right before my next prompt, I get
> 
> Attempt to inungetc() at start of input.

This fixes this particular bug, at any rate.

What's happening is that after expanding !$ to the filename, the lexer
decides the next character isn't a digit, so it's not interested in
parsing a numeric glob; it therefore pushes the first filename
character back into the input.  Then the fun starts: since it's a
redirection, the lexer decides it can stop and return the first word
on the line, so it tries to push the `<' back onto the input as well.
Unfortunately it couldn't because the input stack has just had the
history expansion pushed onto it so there was no way of pushing back
the `<', hence the message.

I've handled this as a special case:  the character is itself pushed
onto the stack for rereading.  This doesn't happen very often ---
judging by the lack of previous bug reports --- so this should be fine.

*** Src/input.c.unget	Wed Aug  7 10:39:23 1996
--- Src/input.c	Wed Aug  7 10:47:11 1996
***************
*** 359,369 ****
  	    inbufleft++;
  	}
  #ifdef DEBUG
!         else {
  	    /* Just for debugging */
  	    fprintf(stderr, "Attempt to inungetc() at start of input.\n");
  	}
  #endif
      }
      if (inalstacktop > inalstack)
  	inalrestore();
--- 359,380 ----
  	    inbufleft++;
  	}
  #ifdef DEBUG
!         else if (!(inbufflags & (INP_ALIAS|INP_CONT))) {
  	    /* Just for debugging */
  	    fprintf(stderr, "Attempt to inungetc() at start of input.\n");
  	}
  #endif
+ 	else {
+ 	    /*
+ 	     * The character is being backed up from a previous input stack
+ 	     * layer.  However, there was an expansion in the middle, so we
+ 	     * can't back up where we want to.  Instead, we just push it
+ 	     * onto the input stack as an extra character.
+ 	     */
+ 	    char *cback = (char *)zcalloc(2);
+ 	    cback[0] = (char) c;
+ 	    inpush(cback, INP_FREE|INP_CONT);
+ 	}
      }
      if (inalstacktop > inalstack)
  	inalrestore();

-- 
Peter Stephenson <pws@xxxxxx>       Tel: +49 33762 77366
WWW:  http://www.ifh.de/~pws/       Fax: +49 33762 77330
Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen
DESY-IfH, 15735 Zeuthen, Germany.



Messages sorted by: Reverse Date, Date, Thread, Author