Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
History substitution fix
- X-seq: zsh-workers 1457
- From: Zoltan Hidvegi <hzoli@xxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxxxxxxx (Zsh hacking and development)
- Subject: History substitution fix
- Date: Thu, 27 Jun 1996 23:40:31 +0200 (MET DST)
- Cc: mark@xxxxxxxxxxxx
The patch below fixes a recently reported by
Mark Hanson <mark@xxxxxxxxxxxx>:
% 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;
Messages sorted by:
Reverse Date,
Date,
Thread,
Author