From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from euclid.skiles.gatech.edu (root@euclid.skiles.gatech.edu [130.207.146.50]) by melb.werple.net.au (8.7.5/8.7.3/2) with ESMTP id JAA26219 for ; Fri, 28 Jun 1996 09:27:52 +1000 (EST) Received: (from list@localhost) by euclid.skiles.gatech.edu (8.7.3/8.7.3) id SAA01485; Thu, 27 Jun 1996 18:31:18 -0400 (EDT) Resent-Date: Thu, 27 Jun 1996 18:31:18 -0400 (EDT) From: Zoltan Hidvegi Message-Id: <199606272140.XAA00782@hzoli.ppp.cs.elte.hu> Subject: History substitution fix To: zsh-workers@math.gatech.edu (Zsh hacking and development) Date: Thu, 27 Jun 1996 23:40:31 +0200 (MET DST) Cc: mark@acucobol.com X-Mailer: ELM [version 2.4ME+ PL17 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Resent-Message-ID: <"ev4V33.0.7N.rkmqn"@euclid> Resent-From: zsh-workers@math.gatech.edu X-Mailing-List: archive/latest/1457 X-Loop: zsh-workers@math.gatech.edu Precedence: list Resent-Sender: zsh-workers-request@math.gatech.edu The patch below fixes a recently reported by Mark Hanson : % 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;