zsh-workers
 help / color / mirror / code / Atom feed
From: Zoltan Hidvegi <hzoli@cs.elte.hu>
To: zsh-workers@math.gatech.edu (Zsh hacking and development)
Cc: mark@acucobol.com
Subject: History substitution fix
Date: Thu, 27 Jun 1996 23:40:31 +0200 (MET DST)	[thread overview]
Message-ID: <199606272140.XAA00782@hzoli.ppp.cs.elte.hu> (raw)

The patch below fixes a recently reported by
Mark Hanson <mark@acucobol.com>:

% echo $!
0
% echo !$

causes an infinite loop.  Please apply this patch and test history
substitutions with various history events containing a bang.

After this patch no additional backslashes will be added if a bang comes
from a history substitution.  This means that in

% echo !
!
% echo !$

the !$ expands to ! instead of \!.

The code than handles bangs in hgetc and hungetc is quite sort but a bit
difficult to understand but there are some long comments which are trying
to explain the situation.

Zoltan


*** Src/hist.c	1996/06/26 23:19:48	2.11
--- Src/hist.c	1996/06/27 21:03:08
***************
*** 118,134 ****
  	    return ' ';
  	}
      }
!     if (alstackind == 1 && !alstack[0] && !stophist &&
! 	c == '\\' && (c = ingetc()) != bangchar)
  	/* the current character c came from a history expansion        *
  	 * (alstackind == 1 && !alstack[0]) and history is not disabled *
! 	 * (e.g. we are not inside qingle quotes). In that case, \!     *
  	 * should be treated as ! (since this \! came from a previous   *
  	 * history line where \ was used to escape the bang). So if     *
  	 * c == '\\' we fetch one more character to see if it's a bang, *
  	 * and if it is not, we unget it and reset c back to '\\'       */
! 	safeinungetc(c), c = '\\';
!     if (stophist || alstackind)
  	/* If the result is a bangchar which came from history or alias  *
  	 * expansion, we treat it as an escaped bangchar, unless history *
  	 * is disabled. If stophist == 1 it only means that history is   *
--- 118,135 ----
  	    return ' ';
  	}
      }
!     if (alstackind == 1 && !alstack[0] && !stophist) {
  	/* the current character c came from a history expansion        *
  	 * (alstackind == 1 && !alstack[0]) and history is not disabled *
! 	 * (e.g. we are not inside single quotes). In that case, \!     *
  	 * should be treated as ! (since this \! came from a previous   *
  	 * history line where \ was used to escape the bang). So if     *
  	 * c == '\\' we fetch one more character to see if it's a bang, *
  	 * and if it is not, we unget it and reset c back to '\\'       */
! 	qbang = 0;
! 	if (c == '\\' && !(qbang = (c = ingetc()) == bangchar))
! 	    safeinungetc(c), c = '\\';
!     } else if (stophist || alstackind)
  	/* If the result is a bangchar which came from history or alias  *
  	 * expansion, we treat it as an escaped bangchar, unless history *
  	 * is disabled. If stophist == 1 it only means that history is   *
***************
*** 535,542 ****
  	}
  #endif
      }
-     /* I have to look at this part more closely to understand what Peter   *
-      * did here (Zoltan)  #######                                          */
      if (doit)
  	inungetc(c);
      if (c == bangchar && stophist < 2 && qbang) {
--- 536,541 ----
***************
*** 552,559 ****
  	 * bangchar was quoted. In some rare cases when more than one      *
  	 * bangs are unget by the lexer, this may give a wrong result, but *
  	 * it can happen only if bangchar is some very unusual character   *
! 	 * (unusual means unusual for a bang like a number).               */
! 	doit = !stophist;
  	qbang = 0;
  	c = '\\';
  	goto escape;
--- 551,560 ----
  	 * bangchar was quoted. In some rare cases when more than one      *
  	 * bangs are unget by the lexer, this may give a wrong result, but *
  	 * it can happen only if bangchar is some very unusual character   *
! 	 * (unusual means unusual for a bang like a number).  If this bang *
! 	 * comes from an alias expansion, no backslash should be really    *
! 	 * unget.                                                          */
! 	doit = !stophist && (!alstackind || (alstackind == 1 && !alstack[0]));
  	qbang = 0;
  	c = '\\';
  	goto escape;



                 reply	other threads:[~1996-06-27 23:27 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=199606272140.XAA00782@hzoli.ppp.cs.elte.hu \
    --to=hzoli@cs.elte.hu \
    --cc=mark@acucobol.com \
    --cc=zsh-workers@math.gatech.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).