From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21652 invoked by alias); 16 Jan 2015 12:57:37 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 34304 Received: (qmail 15117 invoked from network); 16 Jan 2015 12:57:34 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_HI, SPF_HELO_PASS autolearn=ham version=3.3.2 X-AuditID: cbfec7f5-b7fc86d0000066b7-be-54b90aad2cfa Date: Fri, 16 Jan 2015 12:57:12 +0000 From: Peter Stephenson To: Zsh Hackers' List Subject: Re: Crash when capturing command output in completion Message-id: <20150116125712.3ef52e96@pwslap01u.europe.root.pri> In-reply-to: <20150116094436.7803b467@pwslap01u.europe.root.pri> References: <150115135356.ZM23582@torch.brasslantern.com> <150115162748.ZM23670@torch.brasslantern.com> <150115204336.ZM23779@torch.brasslantern.com> <150115212036.ZM23929@torch.brasslantern.com> <20150116094436.7803b467@pwslap01u.europe.root.pri> Organization: Samsung Cambridge Solution Centre X-Mailer: Claws Mail 3.7.9 (GTK+ 2.22.0; i386-redhat-linux-gnu) MIME-version: 1.0 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7bit X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrGLMWRmVeSWpSXmKPExsVy+t/xq7pruXaGGKx7KWdxsPkhkwOjx6qD H5gCGKO4bFJSczLLUov07RK4MpafmchcMFWp4svSq8wNjGckuhg5OSQETCTOT+1ghbDFJC7c W8/WxcjFISSwlFHixY3z7BDOEiaJ3o51jBDONkaJ+9OPMoK0sAioSvzc/Y4dxGYTMJSYumk2 UJyDQ0RAW6L9oxhIWFjATuLQjDNgG3gF7CUONnQzgdicAg4Sd7u+MEPMnMsi0fi1hQUkwS+g L3H17ycmiJPsJWZeOcMI0Swo8WPyPbAaZgEtic3bmlghbHmJzWveMoPYQgLqEjfu7mafwCg0 C0nLLCQts5C0LGBkXsUomlqaXFCclJ5rpFecmFtcmpeul5yfu4kRErZfdzAuPWZ1iFGAg1GJ h9dh044QIdbEsuLK3EOMEhzMSiK8cYw7Q4R4UxIrq1KL8uOLSnNSiw8xMnFwSjUw3rosVrN3 6bs5+son70v4/Xuc5Rq2VGDnCc36SynT7xhl7E/K27M8JfTL9ppfBz4Lxja+euGz4Jen58FX DhyhwkxLin7vPzEvpKbk+abV+s/V7VPLb/3kzulX0C7hTDoV1+Cw5LL5Xc1nhhmnXn6zL/rm UdEQ/XvhT/3nlRfPNF/QW19+6Iv3LyWW4oxEQy3mouJEAHsCQYM5AgAA Only very lightly tested and so probably partial fix --- however, I'll commit this because (i) I'm fairly sure it's going in the right direction (ii) it does work in some cases and hence the shell is less crash-prone (iii) I get to insert a whiny message about the horrible interface which always improves my morale. The first hunk is just a bit of clarity about what belongs to the lex/zle non-interface for future reference. I'll remove the ZSH_OLD_SKIPCOMM code when we have a final fix for this (though it's not actually doing any harm). pws diff --git a/Src/lex.c b/Src/lex.c index b0cd86c..96da1cb 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -90,6 +90,12 @@ int inalmore; int nocorrect; /* + * TBD: the following exported variables are part of the non-interface + * with ZLE for completion. They are poorly named and the whole + * scheme is incredibly brittle. One piece of robustness is applied: + * the variables are only set if LEXFLAGS_ZLE is set. Improvements + * should therefore concentrate on areas with this flag set. + * * Cursor position and line length in zle when the line is * metafied for access from the main shell. */ @@ -113,6 +119,16 @@ mod_export int addedx; /**/ mod_export int wb, we; +/**/ +mod_export int wordbeg; + +/**/ +mod_export int parbegin; + +/**/ +mod_export int parend; + + /* 1 if aliases should not be expanded */ /**/ @@ -134,15 +150,6 @@ mod_export int noaliases; /**/ mod_export int lexflags; -/**/ -mod_export int wordbeg; - -/**/ -mod_export int parbegin; - -/**/ -mod_export int parend; - /* don't recognize comments */ /**/ @@ -585,7 +592,8 @@ gettok(void) if (lexstop) return (errflag) ? LEXERR : ENDINPUT; isfirstln = 0; - wordbeg = inbufct - (qbang && c == bangchar); + if ((lexflags & LEXFLAGS_ZLE)) + wordbeg = inbufct - (qbang && c == bangchar); hwbegin(-1-(qbang && c == bangchar)); /* word includes the last character read and possibly \ before ! */ if (dbparens) { @@ -1813,6 +1821,78 @@ zshlex_raw_back(void) static int skipcomm(void) { +#ifdef ZSH_OLD_SKIPCOMM + int pct = 1, c, start = 1; + + cmdpush(CS_CMDSUBST); + SETPARBEGIN + c = Inpar; + do { + int iswhite; + add(c); + c = hgetc(); + if (itok(c) || lexstop) + break; + iswhite = inblank(c); + switch (c) { + case '(': + pct++; + break; + case ')': + pct--; + break; + case '\\': + add(c); + c = hgetc(); + break; + case '\'': { + int strquote = lexbuf.ptr[-1] == '$'; + add(c); + STOPHIST + while ((c = hgetc()) != '\'' && !lexstop) { + if (c == '\\' && strquote) { + add(c); + c = hgetc(); + } + add(c); + } + ALLOWHIST + break; + } + case '\"': + add(c); + while ((c = hgetc()) != '\"' && !lexstop) + if (c == '\\') { + add(c); + add(hgetc()); + } else + add(c); + break; + case '`': + add(c); + while ((c = hgetc()) != '`' && !lexstop) + if (c == '\\') + add(c), add(hgetc()); + else + add(c); + break; + case '#': + if (start) { + add(c); + while ((c = hgetc()) != '\n' && !lexstop) + add(c); + iswhite = 1; + } + break; + } + start = iswhite; + } + while (pct); + if (!lexstop) + SETPAREND + cmdpop(); + return lexstop; +#else char *new_tokstr; int new_lexstop, new_lex_add_raw; struct lexbufstate new_lexbuf; @@ -1860,6 +1940,18 @@ skipcomm(void) tokstr_raw = new_tokstr; lexbuf_raw = new_lexbuf; lex_add_raw = new_lex_add_raw; + /* + * Don't do any ZLE specials down here: they're only needed + * when we return the string from the recursive parse. + * (TBD: this probably means we should be initialising lexflags + * more consistently.) + * + * Note that in that case we're still using the ZLE line reading + * function at the history layer --- this is consistent with the + * intention of maintaining the history and input layers across + * the recursive parsing. + */ + lexflags &= ~LEXFLAGS_ZLE; if (!parse_event(OUTPAR) || tok != OUTPAR) lexstop = 1; @@ -1907,4 +1999,5 @@ skipcomm(void) cmdpop(); return lexstop; +#endif }