From 126fb61c7c48edb19b9d771e4e517cef710f8bf1 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 16 Feb 2015 17:16:57 +0000 Subject: 34560: Fix $(( that's actually a multiline cmd subst. --- ChangeLog | 2 ++ Src/input.c | 33 +++++++++++++++++++++++++++++++-- Src/lex.c | 4 ++++ Src/zsh.h | 1 + Test/C01arith.ztst | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index f37c218c7..509faffe6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2015-02-16 Peter Stephenson + * 34560: Src/input. Src/lex.c, Src/zsh.h, Test/C01arith.ztst: + * 34558: Doc/Zsh/func.yo: preexec doc erroneously claimed $1 was empty if line removed from history. diff --git a/Src/input.c b/Src/input.c index 9520fdd6d..f919e5757 100644 --- a/Src/input.c +++ b/Src/input.c @@ -330,8 +330,37 @@ inputline(void) } } isfirstch = 1; - /* Put this into the input channel. */ - inputsetline(ingetcline, INP_FREE); + if ((inbufflags & INP_APPEND) && inbuf) { + /* + * We need new input but need to be able to back up + * over the old input, so append this line. + * Pushing the line onto the stack doesn't have the right + * effect. + * + * This is quite a simple and inefficient fix, but currently + * we only need it when backing up over a multi-line $((... + * that turned out to be a command substitution rather than + * a math substitution, which is a very special case. + * So it's not worth rewriting. + */ + char *oinbuf = inbuf; + int newlen = strlen(ingetcline); + int oldlen = (int)(inbufptr - inbuf) + inbufleft; + if (inbufflags & INP_FREE) { + inbuf = realloc(inbuf, oldlen + newlen + 1); + inbufptr += inbuf - oinbuf; + strcpy(inbuf + oldlen, ingetcline); + } else { + /* Paranoia: don't think this is used */ + DPUTS(1, "Appending to unallocated input line."); + } + inbufleft += newlen; + inbufct += newlen; + inbufflags |= INP_FREE; + } else { + /* Put this into the input channel. */ + inputsetline(ingetcline, INP_FREE); + } return 0; } diff --git a/Src/lex.c b/Src/lex.c index 91628d4c2..006848543 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -483,9 +483,13 @@ cmd_or_math(int cs_type) { int oldlen = lexbuf.len; int c; + int oinflags = inbufflags; cmdpush(cs_type); + inbufflags |= INP_APPEND; c = dquote_parse(')', 0); + if (!(oinflags & INP_APPEND)) + inbufflags &= ~INP_APPEND; cmdpop(); *lexbuf.ptr = '\0'; if (!c) { diff --git a/Src/zsh.h b/Src/zsh.h index 94e9ffc9f..dd946d214 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -410,6 +410,7 @@ enum { #define INP_CONT (1<<3) /* continue onto previously stacked input */ #define INP_ALCONT (1<<4) /* stack is continued from alias expn. */ #define INP_LINENO (1<<5) /* update line number */ +#define INP_APPEND (1<<6) /* Append new lines to allow backup */ /* Flags for metafy */ #define META_REALLOC 0 diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst index ea87af257..09c08224e 100644 --- a/Test/C01arith.ztst +++ b/Test/C01arith.ztst @@ -318,3 +318,38 @@ # 0.75 is exactly representable, don't expect rounding error. >0 >0.75 + + # The following tests for a bug that only happens when + # backing up over input read a line at a time, so we'll + # read the input from stdin. + $ZTST_testdir/../Src/zsh -f <<<' + print $((echo first command + ); echo second command) + print third command + ' +0:Backing up a line of input when finding out it's not arithmetic +>first command second command +>third command + + $ZTST_testdir/../Src/zsh -f <<<' + print $((3 + + 4)) + print next line + ' +0:Not needing to back up a line when reading multiline arithmetic +>7 +>next line + + $ZTST_testdir/../Src/zsh -f <<<' + print $((case foo in + bar) + echo not this no, no + ;; + foo) + echo yes, this one + ;; + esac) + print after case in subshell) + ' +0:Non-arithmetic subst with command subsitution parse from hell +>yes, this one after case in subshell -- cgit 1.4.1