|
|
f686d7 |
From 6b8f3f9906ee44be46e022480b6e01755feeaa99 Mon Sep 17 00:00:00 2001
|
|
|
f686d7 |
From: Peter Stephenson <pws@zsh.org>
|
|
|
f686d7 |
Date: Tue, 6 Jan 2015 17:05:17 +0000
|
|
|
f686d7 |
Subject: [PATCH 1/9] Fix command substitutions to parse contents as they are
|
|
|
f686d7 |
read in.
|
|
|
f686d7 |
|
|
|
f686d7 |
Do this by refactoring misnamed lexsave()/lexrestore() to allow
|
|
|
f686d7 |
continuity of history and input.
|
|
|
f686d7 |
|
|
|
f686d7 |
Add test.
|
|
|
f686d7 |
|
|
|
f686d7 |
Upstream-commit: c0d01a6fe0c67911650730cf13a2b9a0db16e59b
|
|
|
f686d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
---
|
|
|
f686d7 |
Src/init.c | 3 +-
|
|
|
f686d7 |
Src/input.c | 13 +-
|
|
|
f686d7 |
Src/lex.c | 498 ++++++++++++++++++++++++++++++++------------------
|
|
|
f686d7 |
Src/parse.c | 29 ++-
|
|
|
f686d7 |
Src/zsh.h | 9 +
|
|
|
f686d7 |
Test/D08cmdsubst.ztst | 42 +++++
|
|
|
f686d7 |
6 files changed, 401 insertions(+), 193 deletions(-)
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/init.c b/Src/init.c
|
|
|
f686d7 |
index 0742a9f..78f171d 100644
|
|
|
f686d7 |
--- a/Src/init.c
|
|
|
f686d7 |
+++ b/Src/init.c
|
|
|
f686d7 |
@@ -129,7 +129,8 @@ loop(int toplevel, int justonce)
|
|
|
f686d7 |
use_exit_printed = 0;
|
|
|
f686d7 |
intr(); /* interrupts on */
|
|
|
f686d7 |
lexinit(); /* initialize lexical state */
|
|
|
f686d7 |
- if (!(prog = parse_event())) { /* if we couldn't parse a list */
|
|
|
f686d7 |
+ if (!(prog = parse_event(ENDINPUT))) {
|
|
|
f686d7 |
+ /* if we couldn't parse a list */
|
|
|
f686d7 |
hend(NULL);
|
|
|
f686d7 |
if ((tok == ENDINPUT && !errflag) ||
|
|
|
f686d7 |
(tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) ||
|
|
|
f686d7 |
diff --git a/Src/input.c b/Src/input.c
|
|
|
f686d7 |
index 5cff22d..1579762 100644
|
|
|
f686d7 |
--- a/Src/input.c
|
|
|
f686d7 |
+++ b/Src/input.c
|
|
|
f686d7 |
@@ -175,12 +175,12 @@ shingetline(void)
|
|
|
f686d7 |
/* Get the next character from the input.
|
|
|
f686d7 |
* Will call inputline() to get a new line where necessary.
|
|
|
f686d7 |
*/
|
|
|
f686d7 |
-
|
|
|
f686d7 |
+
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
int
|
|
|
f686d7 |
ingetc(void)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
- int lastc;
|
|
|
f686d7 |
+ int lastc = ' ';
|
|
|
f686d7 |
|
|
|
f686d7 |
if (lexstop)
|
|
|
f686d7 |
return ' ';
|
|
|
f686d7 |
@@ -192,7 +192,7 @@ ingetc(void)
|
|
|
f686d7 |
continue;
|
|
|
f686d7 |
if (((inbufflags & INP_LINENO) || !strin) && lastc == '\n')
|
|
|
f686d7 |
lineno++;
|
|
|
f686d7 |
- return lastc;
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
/*
|
|
|
f686d7 |
@@ -204,7 +204,7 @@ ingetc(void)
|
|
|
f686d7 |
*/
|
|
|
f686d7 |
if (!inbufct && (strin || errflag)) {
|
|
|
f686d7 |
lexstop = 1;
|
|
|
f686d7 |
- return ' ';
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
/* If the next element down the input stack is a continuation of
|
|
|
f686d7 |
* this, use it.
|
|
|
f686d7 |
@@ -215,8 +215,10 @@ ingetc(void)
|
|
|
f686d7 |
}
|
|
|
f686d7 |
/* As a last resort, get some more input */
|
|
|
f686d7 |
if (inputline())
|
|
|
f686d7 |
- return ' ';
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
+ zshlex_raw_add(lastc);
|
|
|
f686d7 |
+ return lastc;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
/* Read a line from the current command stream and store it as input */
|
|
|
f686d7 |
@@ -421,6 +423,7 @@ inungetc(int c)
|
|
|
f686d7 |
inbufleft = 0;
|
|
|
f686d7 |
inbuf = inbufptr = "";
|
|
|
f686d7 |
}
|
|
|
f686d7 |
+ zshlex_raw_back();
|
|
|
f686d7 |
}
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/lex.c b/Src/lex.c
|
|
|
f686d7 |
index 82bf848..bcceda6 100644
|
|
|
f686d7 |
--- a/Src/lex.c
|
|
|
f686d7 |
+++ b/Src/lex.c
|
|
|
f686d7 |
@@ -146,6 +146,16 @@ mod_export int parend;
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
mod_export int nocomments;
|
|
|
f686d7 |
|
|
|
f686d7 |
+/* add raw input characters while parsing command substitution */
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+static int lex_add_raw;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/* variables associated with the above */
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+static char *tokstr_raw, *bptr_raw;
|
|
|
f686d7 |
+static int len_raw, bsiz_raw;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
/* text of punctuation tokens */
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
@@ -214,6 +224,11 @@ struct lexstack {
|
|
|
f686d7 |
char *bptr;
|
|
|
f686d7 |
int bsiz;
|
|
|
f686d7 |
int len;
|
|
|
f686d7 |
+ int lex_add_raw;
|
|
|
f686d7 |
+ char *tokstr_raw;
|
|
|
f686d7 |
+ char *bptr_raw;
|
|
|
f686d7 |
+ int bsiz_raw;
|
|
|
f686d7 |
+ int len_raw;
|
|
|
f686d7 |
short *chwords;
|
|
|
f686d7 |
int chwordlen;
|
|
|
f686d7 |
int chwordpos;
|
|
|
f686d7 |
@@ -239,89 +254,121 @@ struct lexstack {
|
|
|
f686d7 |
|
|
|
f686d7 |
static struct lexstack *lstack = NULL;
|
|
|
f686d7 |
|
|
|
f686d7 |
-/* save the lexical state */
|
|
|
f686d7 |
+/* save the context or parts thereof */
|
|
|
f686d7 |
|
|
|
f686d7 |
/* is this a hack or what? */
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
mod_export void
|
|
|
f686d7 |
-lexsave(void)
|
|
|
f686d7 |
+lexsave_partial(int parts)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
struct lexstack *ls;
|
|
|
f686d7 |
|
|
|
f686d7 |
ls = (struct lexstack *)malloc(sizeof(struct lexstack));
|
|
|
f686d7 |
|
|
|
f686d7 |
- ls->incmdpos = incmdpos;
|
|
|
f686d7 |
- ls->incond = incond;
|
|
|
f686d7 |
- ls->incasepat = incasepat;
|
|
|
f686d7 |
- ls->dbparens = dbparens;
|
|
|
f686d7 |
- ls->isfirstln = isfirstln;
|
|
|
f686d7 |
- ls->isfirstch = isfirstch;
|
|
|
f686d7 |
- ls->histactive = histactive;
|
|
|
f686d7 |
- ls->histdone = histdone;
|
|
|
f686d7 |
- ls->lexflags = lexflags;
|
|
|
f686d7 |
- ls->stophist = stophist;
|
|
|
f686d7 |
- stophist = 0;
|
|
|
f686d7 |
- if (!lstack) {
|
|
|
f686d7 |
- /* top level, make this version visible to ZLE */
|
|
|
f686d7 |
- zle_chline = chline;
|
|
|
f686d7 |
- /* ensure line stored is NULL-terminated */
|
|
|
f686d7 |
- if (hptr)
|
|
|
f686d7 |
- *hptr = '\0';
|
|
|
f686d7 |
+ if (parts & ZCONTEXT_LEX) {
|
|
|
f686d7 |
+ ls->incmdpos = incmdpos;
|
|
|
f686d7 |
+ ls->incond = incond;
|
|
|
f686d7 |
+ ls->incasepat = incasepat;
|
|
|
f686d7 |
+ ls->dbparens = dbparens;
|
|
|
f686d7 |
+ ls->isfirstln = isfirstln;
|
|
|
f686d7 |
+ ls->isfirstch = isfirstch;
|
|
|
f686d7 |
+ ls->lexflags = lexflags;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ ls->tok = tok;
|
|
|
f686d7 |
+ ls->isnewlin = isnewlin;
|
|
|
f686d7 |
+ ls->tokstr = tokstr;
|
|
|
f686d7 |
+ ls->zshlextext = zshlextext;
|
|
|
f686d7 |
+ ls->bptr = bptr;
|
|
|
f686d7 |
+ ls->bsiz = bsiz;
|
|
|
f686d7 |
+ ls->len = len;
|
|
|
f686d7 |
+ ls->lex_add_raw = lex_add_raw;
|
|
|
f686d7 |
+ ls->tokstr_raw = tokstr_raw;
|
|
|
f686d7 |
+ ls->bptr_raw = bptr_raw;
|
|
|
f686d7 |
+ ls->bsiz_raw = bsiz_raw;
|
|
|
f686d7 |
+ ls->len_raw = len_raw;
|
|
|
f686d7 |
+ ls->lexstop = lexstop;
|
|
|
f686d7 |
+ ls->toklineno = toklineno;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ tokstr = zshlextext = bptr = NULL;
|
|
|
f686d7 |
+ bsiz = 256;
|
|
|
f686d7 |
+ tokstr_raw = bptr_raw = NULL;
|
|
|
f686d7 |
+ bsiz_raw = len_raw = lex_add_raw = 0;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ inredir = 0;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ if (parts & ZCONTEXT_HIST) {
|
|
|
f686d7 |
+ if (!lstack) {
|
|
|
f686d7 |
+ /* top level, make this version visible to ZLE */
|
|
|
f686d7 |
+ zle_chline = chline;
|
|
|
f686d7 |
+ /* ensure line stored is NULL-terminated */
|
|
|
f686d7 |
+ if (hptr)
|
|
|
f686d7 |
+ *hptr = '\0';
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ ls->histactive = histactive;
|
|
|
f686d7 |
+ ls->histdone = histdone;
|
|
|
f686d7 |
+ ls->stophist = stophist;
|
|
|
f686d7 |
+ ls->hline = chline;
|
|
|
f686d7 |
+ ls->hptr = hptr;
|
|
|
f686d7 |
+ ls->chwords = chwords;
|
|
|
f686d7 |
+ ls->chwordlen = chwordlen;
|
|
|
f686d7 |
+ ls->chwordpos = chwordpos;
|
|
|
f686d7 |
+ ls->hwgetword = hwgetword;
|
|
|
f686d7 |
+ ls->hgetc = hgetc;
|
|
|
f686d7 |
+ ls->hungetc = hungetc;
|
|
|
f686d7 |
+ ls->hwaddc = hwaddc;
|
|
|
f686d7 |
+ ls->hwbegin = hwbegin;
|
|
|
f686d7 |
+ ls->hwend = hwend;
|
|
|
f686d7 |
+ ls->addtoline = addtoline;
|
|
|
f686d7 |
+ ls->hlinesz = hlinesz;
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * We save and restore the command stack with history
|
|
|
f686d7 |
+ * as it's visible to the user interactively, so if
|
|
|
f686d7 |
+ * we're preserving history state we'll continue to
|
|
|
f686d7 |
+ * show the current set of commands from input.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ ls->cstack = cmdstack;
|
|
|
f686d7 |
+ ls->csp = cmdsp;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ stophist = 0;
|
|
|
f686d7 |
+ chline = NULL;
|
|
|
f686d7 |
+ hptr = NULL;
|
|
|
f686d7 |
+ histactive = 0;
|
|
|
f686d7 |
+ cmdstack = (unsigned char *)zalloc(CMDSTACKSZ);
|
|
|
f686d7 |
+ cmdsp = 0;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ if (parts & ZCONTEXT_PARSE) {
|
|
|
f686d7 |
+ ls->hdocs = hdocs;
|
|
|
f686d7 |
+ ls->eclen = eclen;
|
|
|
f686d7 |
+ ls->ecused = ecused;
|
|
|
f686d7 |
+ ls->ecnpats = ecnpats;
|
|
|
f686d7 |
+ ls->ecbuf = ecbuf;
|
|
|
f686d7 |
+ ls->ecstrs = ecstrs;
|
|
|
f686d7 |
+ ls->ecsoffs = ecsoffs;
|
|
|
f686d7 |
+ ls->ecssub = ecssub;
|
|
|
f686d7 |
+ ls->ecnfunc = ecnfunc;
|
|
|
f686d7 |
+ ecbuf = NULL;
|
|
|
f686d7 |
+ hdocs = NULL;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
- ls->hline = chline;
|
|
|
f686d7 |
- chline = NULL;
|
|
|
f686d7 |
- ls->hptr = hptr;
|
|
|
f686d7 |
- hptr = NULL;
|
|
|
f686d7 |
- ls->hlinesz = hlinesz;
|
|
|
f686d7 |
- ls->cstack = cmdstack;
|
|
|
f686d7 |
- ls->csp = cmdsp;
|
|
|
f686d7 |
- cmdstack = (unsigned char *)zalloc(CMDSTACKSZ);
|
|
|
f686d7 |
- ls->tok = tok;
|
|
|
f686d7 |
- ls->isnewlin = isnewlin;
|
|
|
f686d7 |
- ls->tokstr = tokstr;
|
|
|
f686d7 |
- ls->zshlextext = zshlextext;
|
|
|
f686d7 |
- ls->bptr = bptr;
|
|
|
f686d7 |
- tokstr = zshlextext = bptr = NULL;
|
|
|
f686d7 |
- ls->bsiz = bsiz;
|
|
|
f686d7 |
- bsiz = 256;
|
|
|
f686d7 |
- ls->len = len;
|
|
|
f686d7 |
- ls->chwords = chwords;
|
|
|
f686d7 |
- ls->chwordlen = chwordlen;
|
|
|
f686d7 |
- ls->chwordpos = chwordpos;
|
|
|
f686d7 |
- ls->hwgetword = hwgetword;
|
|
|
f686d7 |
- ls->lexstop = lexstop;
|
|
|
f686d7 |
- ls->hdocs = hdocs;
|
|
|
f686d7 |
- ls->hgetc = hgetc;
|
|
|
f686d7 |
- ls->hungetc = hungetc;
|
|
|
f686d7 |
- ls->hwaddc = hwaddc;
|
|
|
f686d7 |
- ls->hwbegin = hwbegin;
|
|
|
f686d7 |
- ls->hwend = hwend;
|
|
|
f686d7 |
- ls->addtoline = addtoline;
|
|
|
f686d7 |
- ls->eclen = eclen;
|
|
|
f686d7 |
- ls->ecused = ecused;
|
|
|
f686d7 |
- ls->ecnpats = ecnpats;
|
|
|
f686d7 |
- ls->ecbuf = ecbuf;
|
|
|
f686d7 |
- ls->ecstrs = ecstrs;
|
|
|
f686d7 |
- ls->ecsoffs = ecsoffs;
|
|
|
f686d7 |
- ls->ecssub = ecssub;
|
|
|
f686d7 |
- ls->ecnfunc = ecnfunc;
|
|
|
f686d7 |
- ls->toklineno = toklineno;
|
|
|
f686d7 |
- cmdsp = 0;
|
|
|
f686d7 |
- inredir = 0;
|
|
|
f686d7 |
- hdocs = NULL;
|
|
|
f686d7 |
- histactive = 0;
|
|
|
f686d7 |
- ecbuf = NULL;
|
|
|
f686d7 |
|
|
|
f686d7 |
ls->next = lstack;
|
|
|
f686d7 |
lstack = ls;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
-/* restore lexical state */
|
|
|
f686d7 |
+/* save context in full */
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
mod_export void
|
|
|
f686d7 |
-lexrestore(void)
|
|
|
f686d7 |
+lexsave(void)
|
|
|
f686d7 |
+{
|
|
|
f686d7 |
+ lexsave_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
|
|
|
f686d7 |
+}
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/* restore context or part therefore */
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+mod_export void
|
|
|
f686d7 |
+lexrestore_partial(int parts)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
struct lexstack *ln = lstack;
|
|
|
f686d7 |
|
|
|
f686d7 |
@@ -330,65 +377,89 @@ lexrestore(void)
|
|
|
f686d7 |
queue_signals();
|
|
|
f686d7 |
lstack = lstack->next;
|
|
|
f686d7 |
|
|
|
f686d7 |
- if (!lstack) {
|
|
|
f686d7 |
- /* Back to top level: don't need special ZLE value */
|
|
|
f686d7 |
- DPUTS(ln->hline != zle_chline, "BUG: Ouch, wrong chline for ZLE");
|
|
|
f686d7 |
- zle_chline = NULL;
|
|
|
f686d7 |
+ if (parts & ZCONTEXT_LEX) {
|
|
|
f686d7 |
+ incmdpos = ln->incmdpos;
|
|
|
f686d7 |
+ incond = ln->incond;
|
|
|
f686d7 |
+ incasepat = ln->incasepat;
|
|
|
f686d7 |
+ dbparens = ln->dbparens;
|
|
|
f686d7 |
+ isfirstln = ln->isfirstln;
|
|
|
f686d7 |
+ isfirstch = ln->isfirstch;
|
|
|
f686d7 |
+ lexflags = ln->lexflags;
|
|
|
f686d7 |
+ tok = ln->tok;
|
|
|
f686d7 |
+ isnewlin = ln->isnewlin;
|
|
|
f686d7 |
+ tokstr = ln->tokstr;
|
|
|
f686d7 |
+ zshlextext = ln->zshlextext;
|
|
|
f686d7 |
+ bptr = ln->bptr;
|
|
|
f686d7 |
+ bsiz = ln->bsiz;
|
|
|
f686d7 |
+ len = ln->len;
|
|
|
f686d7 |
+ lex_add_raw = ln->lex_add_raw;
|
|
|
f686d7 |
+ tokstr_raw = ln->tokstr_raw;
|
|
|
f686d7 |
+ bptr_raw = ln->bptr_raw;
|
|
|
f686d7 |
+ bsiz_raw = ln->bsiz_raw;
|
|
|
f686d7 |
+ len_raw = ln->len_raw;
|
|
|
f686d7 |
+ lexstop = ln->lexstop;
|
|
|
f686d7 |
+ toklineno = ln->toklineno;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ if (parts & ZCONTEXT_HIST) {
|
|
|
f686d7 |
+ if (!lstack) {
|
|
|
f686d7 |
+ /* Back to top level: don't need special ZLE value */
|
|
|
f686d7 |
+ DPUTS(ln->hline != zle_chline, "BUG: Ouch, wrong chline for ZLE");
|
|
|
f686d7 |
+ zle_chline = NULL;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ histactive = ln->histactive;
|
|
|
f686d7 |
+ histdone = ln->histdone;
|
|
|
f686d7 |
+ stophist = ln->stophist;
|
|
|
f686d7 |
+ chline = ln->hline;
|
|
|
f686d7 |
+ hptr = ln->hptr;
|
|
|
f686d7 |
+ chwords = ln->chwords;
|
|
|
f686d7 |
+ chwordlen = ln->chwordlen;
|
|
|
f686d7 |
+ chwordpos = ln->chwordpos;
|
|
|
f686d7 |
+ hwgetword = ln->hwgetword;
|
|
|
f686d7 |
+ hgetc = ln->hgetc;
|
|
|
f686d7 |
+ hungetc = ln->hungetc;
|
|
|
f686d7 |
+ hwaddc = ln->hwaddc;
|
|
|
f686d7 |
+ hwbegin = ln->hwbegin;
|
|
|
f686d7 |
+ hwend = ln->hwend;
|
|
|
f686d7 |
+ addtoline = ln->addtoline;
|
|
|
f686d7 |
+ hlinesz = ln->hlinesz;
|
|
|
f686d7 |
+ if (cmdstack)
|
|
|
f686d7 |
+ zfree(cmdstack, CMDSTACKSZ);
|
|
|
f686d7 |
+ cmdstack = ln->cstack;
|
|
|
f686d7 |
+ cmdsp = ln->csp;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ if (parts & ZCONTEXT_PARSE) {
|
|
|
f686d7 |
+ if (ecbuf)
|
|
|
f686d7 |
+ zfree(ecbuf, eclen);
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ hdocs = ln->hdocs;
|
|
|
f686d7 |
+ eclen = ln->eclen;
|
|
|
f686d7 |
+ ecused = ln->ecused;
|
|
|
f686d7 |
+ ecnpats = ln->ecnpats;
|
|
|
f686d7 |
+ ecbuf = ln->ecbuf;
|
|
|
f686d7 |
+ ecstrs = ln->ecstrs;
|
|
|
f686d7 |
+ ecsoffs = ln->ecsoffs;
|
|
|
f686d7 |
+ ecssub = ln->ecssub;
|
|
|
f686d7 |
+ ecnfunc = ln->ecnfunc;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ errflag = 0;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
- incmdpos = ln->incmdpos;
|
|
|
f686d7 |
- incond = ln->incond;
|
|
|
f686d7 |
- incasepat = ln->incasepat;
|
|
|
f686d7 |
- dbparens = ln->dbparens;
|
|
|
f686d7 |
- isfirstln = ln->isfirstln;
|
|
|
f686d7 |
- isfirstch = ln->isfirstch;
|
|
|
f686d7 |
- histactive = ln->histactive;
|
|
|
f686d7 |
- histdone = ln->histdone;
|
|
|
f686d7 |
- lexflags = ln->lexflags;
|
|
|
f686d7 |
- stophist = ln->stophist;
|
|
|
f686d7 |
- chline = ln->hline;
|
|
|
f686d7 |
- hptr = ln->hptr;
|
|
|
f686d7 |
- if (cmdstack)
|
|
|
f686d7 |
- zfree(cmdstack, CMDSTACKSZ);
|
|
|
f686d7 |
- cmdstack = ln->cstack;
|
|
|
f686d7 |
- cmdsp = ln->csp;
|
|
|
f686d7 |
- tok = ln->tok;
|
|
|
f686d7 |
- isnewlin = ln->isnewlin;
|
|
|
f686d7 |
- tokstr = ln->tokstr;
|
|
|
f686d7 |
- zshlextext = ln->zshlextext;
|
|
|
f686d7 |
- bptr = ln->bptr;
|
|
|
f686d7 |
- bsiz = ln->bsiz;
|
|
|
f686d7 |
- len = ln->len;
|
|
|
f686d7 |
- chwords = ln->chwords;
|
|
|
f686d7 |
- chwordlen = ln->chwordlen;
|
|
|
f686d7 |
- chwordpos = ln->chwordpos;
|
|
|
f686d7 |
- hwgetword = ln->hwgetword;
|
|
|
f686d7 |
- lexstop = ln->lexstop;
|
|
|
f686d7 |
- hdocs = ln->hdocs;
|
|
|
f686d7 |
- hgetc = ln->hgetc;
|
|
|
f686d7 |
- hungetc = ln->hungetc;
|
|
|
f686d7 |
- hwaddc = ln->hwaddc;
|
|
|
f686d7 |
- hwbegin = ln->hwbegin;
|
|
|
f686d7 |
- hwend = ln->hwend;
|
|
|
f686d7 |
- addtoline = ln->addtoline;
|
|
|
f686d7 |
- if (ecbuf)
|
|
|
f686d7 |
- zfree(ecbuf, eclen);
|
|
|
f686d7 |
- eclen = ln->eclen;
|
|
|
f686d7 |
- ecused = ln->ecused;
|
|
|
f686d7 |
- ecnpats = ln->ecnpats;
|
|
|
f686d7 |
- ecbuf = ln->ecbuf;
|
|
|
f686d7 |
- ecstrs = ln->ecstrs;
|
|
|
f686d7 |
- ecsoffs = ln->ecsoffs;
|
|
|
f686d7 |
- ecssub = ln->ecssub;
|
|
|
f686d7 |
- ecnfunc = ln->ecnfunc;
|
|
|
f686d7 |
- hlinesz = ln->hlinesz;
|
|
|
f686d7 |
- toklineno = ln->toklineno;
|
|
|
f686d7 |
- errflag = 0;
|
|
|
f686d7 |
free(ln);
|
|
|
f686d7 |
|
|
|
f686d7 |
unqueue_signals();
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
+/* complete restore context */
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+mod_export void
|
|
|
f686d7 |
+lexrestore(void)
|
|
|
f686d7 |
+{
|
|
|
f686d7 |
+ lexrestore_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
|
|
|
f686d7 |
+}
|
|
|
f686d7 |
+
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
void
|
|
|
f686d7 |
zshlex(void)
|
|
|
f686d7 |
@@ -1889,80 +1960,151 @@ exalias(void)
|
|
|
f686d7 |
return 0;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
-/* skip (...) */
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+void
|
|
|
f686d7 |
+zshlex_raw_add(int c)
|
|
|
f686d7 |
+{
|
|
|
f686d7 |
+ if (!lex_add_raw)
|
|
|
f686d7 |
+ return;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ *bptr_raw++ = c;
|
|
|
f686d7 |
+ if (bsiz_raw == ++len_raw) {
|
|
|
f686d7 |
+ int newbsiz = bsiz_raw * 2;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ tokstr_raw = (char *)hrealloc(tokstr_raw, bsiz_raw, newbsiz);
|
|
|
f686d7 |
+ bptr_raw = tokstr_raw + len_raw;
|
|
|
f686d7 |
+ memset(bptr_raw, 0, newbsiz - bsiz_raw);
|
|
|
f686d7 |
+ bsiz_raw = newbsiz;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+}
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+void
|
|
|
f686d7 |
+zshlex_raw_back(void)
|
|
|
f686d7 |
+{
|
|
|
f686d7 |
+ if (!lex_add_raw)
|
|
|
f686d7 |
+ return;
|
|
|
f686d7 |
+ bptr_raw--;
|
|
|
f686d7 |
+ len_raw--;
|
|
|
f686d7 |
+}
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/*
|
|
|
f686d7 |
+ * Skip (...) for command-style substitutions: $(...), <(...), >(...)
|
|
|
f686d7 |
+ *
|
|
|
f686d7 |
+ * In order to ensure we don't stop at closing parentheses with
|
|
|
f686d7 |
+ * some other syntactic significance, we'll parse the input until
|
|
|
f686d7 |
+ * we find an unmatched closing parenthesis. However, we'll throw
|
|
|
f686d7 |
+ * away the result of the parsing and just keep the string we've built
|
|
|
f686d7 |
+ * up on the way.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
static int
|
|
|
f686d7 |
skipcomm(void)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
- int pct = 1, c, start = 1;
|
|
|
f686d7 |
+ char *new_tokstr, *new_bptr = bptr_raw;
|
|
|
f686d7 |
+ int new_len, new_bsiz, new_lexstop, new_lex_add_raw;
|
|
|
f686d7 |
|
|
|
f686d7 |
cmdpush(CS_CMDSUBST);
|
|
|
f686d7 |
SETPARBEGIN
|
|
|
f686d7 |
- c = Inpar;
|
|
|
f686d7 |
- do {
|
|
|
f686d7 |
- int iswhite;
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- c = hgetc();
|
|
|
f686d7 |
- if (itok(c) || lexstop)
|
|
|
f686d7 |
- break;
|
|
|
f686d7 |
- iswhite = inblank(c);
|
|
|
f686d7 |
- switch (c) {
|
|
|
f686d7 |
- case '(':
|
|
|
f686d7 |
- pct++;
|
|
|
f686d7 |
- break;
|
|
|
f686d7 |
- case ')':
|
|
|
f686d7 |
- pct--;
|
|
|
f686d7 |
- break;
|
|
|
f686d7 |
- case '\\':
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- c = hgetc();
|
|
|
f686d7 |
- break;
|
|
|
f686d7 |
- case '\'': {
|
|
|
f686d7 |
- int strquote = bptr[-1] == '$';
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- STOPHIST
|
|
|
f686d7 |
- while ((c = hgetc()) != '\'' && !lexstop) {
|
|
|
f686d7 |
- if (c == '\\' && strquote) {
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- c = hgetc();
|
|
|
f686d7 |
- }
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- }
|
|
|
f686d7 |
- ALLOWHIST
|
|
|
f686d7 |
- break;
|
|
|
f686d7 |
- }
|
|
|
f686d7 |
- case '\"':
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- while ((c = hgetc()) != '\"' && !lexstop)
|
|
|
f686d7 |
- if (c == '\\') {
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- add(hgetc());
|
|
|
f686d7 |
- } else
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- break;
|
|
|
f686d7 |
- case '`':
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- while ((c = hgetc()) != '`' && !lexstop)
|
|
|
f686d7 |
- if (c == '\\')
|
|
|
f686d7 |
- add(c), add(hgetc());
|
|
|
f686d7 |
- else
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- break;
|
|
|
f686d7 |
- case '#':
|
|
|
f686d7 |
- if (start) {
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- while ((c = hgetc()) != '\n' && !lexstop)
|
|
|
f686d7 |
- add(c);
|
|
|
f686d7 |
- iswhite = 1;
|
|
|
f686d7 |
- }
|
|
|
f686d7 |
- break;
|
|
|
f686d7 |
+ add(Inpar);
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ new_lex_add_raw = lex_add_raw + 1;
|
|
|
f686d7 |
+ if (!lex_add_raw) {
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * We'll combine the string so far with the input
|
|
|
f686d7 |
+ * read in for the command substitution. To do this
|
|
|
f686d7 |
+ * we'll just propagate the current tokstr etc. as the
|
|
|
f686d7 |
+ * variables used for adding raw input, and
|
|
|
f686d7 |
+ * ensure we swap those for the real tokstr etc. at the end.
|
|
|
f686d7 |
+ *
|
|
|
f686d7 |
+ * However, we need to save and restore the rest of the
|
|
|
f686d7 |
+ * lexical and parse state as we're effectively parsing
|
|
|
f686d7 |
+ * an internal string. Because we're still parsing it from
|
|
|
f686d7 |
+ * the original input source (we have to --- we don't know
|
|
|
f686d7 |
+ * when to stop inputting it otherwise and can't rely on
|
|
|
f686d7 |
+ * the input being recoverable until we've read it) we need
|
|
|
f686d7 |
+ * to keep the same history context.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ new_tokstr = tokstr;
|
|
|
f686d7 |
+ new_bptr = bptr;
|
|
|
f686d7 |
+ new_len = len;
|
|
|
f686d7 |
+ new_bsiz = bsiz;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ lexsave_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
|
|
|
f686d7 |
+ } else {
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * Set up for nested command subsitution, however
|
|
|
f686d7 |
+ * we don't actually need the string until we get
|
|
|
f686d7 |
+ * back to the top level and recover the lot.
|
|
|
f686d7 |
+ * The $() body just appears empty.
|
|
|
f686d7 |
+ *
|
|
|
f686d7 |
+ * We do need to propagate the raw variables which would
|
|
|
f686d7 |
+ * otherwise by cleared, though.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ new_tokstr = tokstr_raw;
|
|
|
f686d7 |
+ new_bptr = bptr_raw;
|
|
|
f686d7 |
+ new_len = len_raw;
|
|
|
f686d7 |
+ new_bsiz = bsiz_raw;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ lexsave_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ tokstr_raw = new_tokstr;
|
|
|
f686d7 |
+ bsiz_raw = new_bsiz;
|
|
|
f686d7 |
+ len_raw = new_len;
|
|
|
f686d7 |
+ bptr_raw = new_bptr;
|
|
|
f686d7 |
+ lex_add_raw = new_lex_add_raw;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ if (!parse_event(OUTPAR) || tok != OUTPAR)
|
|
|
f686d7 |
+ lexstop = 1;
|
|
|
f686d7 |
+ /* Outpar lexical token gets added in caller if present */
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * We're going to keep the full raw input string
|
|
|
f686d7 |
+ * as the current token string after popping the stack.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ new_tokstr = tokstr_raw;
|
|
|
f686d7 |
+ new_bptr = bptr_raw;
|
|
|
f686d7 |
+ new_len = len_raw;
|
|
|
f686d7 |
+ new_bsiz = bsiz_raw;
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * We're also going to propagate the lexical state:
|
|
|
f686d7 |
+ * if we couldn't parse the command substitution we
|
|
|
f686d7 |
+ * can't continue.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ new_lexstop = lexstop;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ lexrestore_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ if (lex_add_raw) {
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * Keep going, so retain the raw variables.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ tokstr_raw = new_tokstr;
|
|
|
f686d7 |
+ bptr_raw = new_bptr;
|
|
|
f686d7 |
+ len_raw = new_len;
|
|
|
f686d7 |
+ bsiz_raw = new_bsiz;
|
|
|
f686d7 |
+ } else {
|
|
|
f686d7 |
+ if (!new_lexstop) {
|
|
|
f686d7 |
+ /* Ignore the ')' added on input */
|
|
|
f686d7 |
+ new_len--;
|
|
|
f686d7 |
+ *--new_bptr = '\0';
|
|
|
f686d7 |
}
|
|
|
f686d7 |
- start = iswhite;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * Convince the rest of lex.c we were examining a string
|
|
|
f686d7 |
+ * all along.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ tokstr = new_tokstr;
|
|
|
f686d7 |
+ bptr = new_bptr;
|
|
|
f686d7 |
+ len = new_len;
|
|
|
f686d7 |
+ bsiz = new_bsiz;
|
|
|
f686d7 |
+ lexstop = new_lexstop;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
- while (pct);
|
|
|
f686d7 |
+
|
|
|
f686d7 |
if (!lexstop)
|
|
|
f686d7 |
SETPAREND
|
|
|
f686d7 |
cmdpop();
|
|
|
f686d7 |
+
|
|
|
f686d7 |
return lexstop;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
diff --git a/Src/parse.c b/Src/parse.c
|
|
|
f686d7 |
index 753080d..b0a7624 100644
|
|
|
f686d7 |
--- a/Src/parse.c
|
|
|
f686d7 |
+++ b/Src/parse.c
|
|
|
f686d7 |
@@ -360,7 +360,8 @@ ecstrcode(char *s)
|
|
|
f686d7 |
|
|
|
f686d7 |
/* Initialise wordcode buffer. */
|
|
|
f686d7 |
|
|
|
f686d7 |
-static void
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+void
|
|
|
f686d7 |
init_parse(void)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
if (ecbuf) zfree(ecbuf, eclen);
|
|
|
f686d7 |
@@ -439,11 +440,15 @@ clear_hdocs()
|
|
|
f686d7 |
* event : ENDINPUT
|
|
|
f686d7 |
* | SEPER
|
|
|
f686d7 |
* | sublist [ SEPER | AMPER | AMPERBANG ]
|
|
|
f686d7 |
+ *
|
|
|
f686d7 |
+ * cmdsubst indicates our event is part of a command-style
|
|
|
f686d7 |
+ * substitution terminated by the token indicationg, usual closing
|
|
|
f686d7 |
+ * parenthesis. In other cases endtok is ENDINPUT.
|
|
|
f686d7 |
*/
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
Eprog
|
|
|
f686d7 |
-parse_event(void)
|
|
|
f686d7 |
+parse_event(int endtok)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
tok = ENDINPUT;
|
|
|
f686d7 |
incmdpos = 1;
|
|
|
f686d7 |
@@ -451,36 +456,42 @@ parse_event(void)
|
|
|
f686d7 |
zshlex();
|
|
|
f686d7 |
init_parse();
|
|
|
f686d7 |
|
|
|
f686d7 |
- if (!par_event()) {
|
|
|
f686d7 |
+ if (!par_event(endtok)) {
|
|
|
f686d7 |
clear_hdocs();
|
|
|
f686d7 |
return NULL;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
+ if (endtok != ENDINPUT) {
|
|
|
f686d7 |
+ /* don't need to build an eprog for this */
|
|
|
f686d7 |
+ return &dummy_eprog;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
return bld_eprog();
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
-static int
|
|
|
f686d7 |
-par_event(void)
|
|
|
f686d7 |
+int
|
|
|
f686d7 |
+par_event(int endtok)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
int r = 0, p, c = 0;
|
|
|
f686d7 |
|
|
|
f686d7 |
while (tok == SEPER) {
|
|
|
f686d7 |
- if (isnewlin > 0)
|
|
|
f686d7 |
+ if (isnewlin > 0 && endtok == ENDINPUT)
|
|
|
f686d7 |
return 0;
|
|
|
f686d7 |
zshlex();
|
|
|
f686d7 |
}
|
|
|
f686d7 |
if (tok == ENDINPUT)
|
|
|
f686d7 |
return 0;
|
|
|
f686d7 |
+ if (tok == endtok)
|
|
|
f686d7 |
+ return 0;
|
|
|
f686d7 |
|
|
|
f686d7 |
p = ecadd(0);
|
|
|
f686d7 |
|
|
|
f686d7 |
if (par_sublist(&c)) {
|
|
|
f686d7 |
- if (tok == ENDINPUT) {
|
|
|
f686d7 |
+ if (tok == ENDINPUT || tok == endtok) {
|
|
|
f686d7 |
set_list_code(p, Z_SYNC, c);
|
|
|
f686d7 |
r = 1;
|
|
|
f686d7 |
} else if (tok == SEPER) {
|
|
|
f686d7 |
set_list_code(p, Z_SYNC, c);
|
|
|
f686d7 |
- if (isnewlin <= 0)
|
|
|
f686d7 |
+ if (isnewlin <= 0 || endtok != ENDINPUT)
|
|
|
f686d7 |
zshlex();
|
|
|
f686d7 |
r = 1;
|
|
|
f686d7 |
} else if (tok == AMPER) {
|
|
|
f686d7 |
@@ -509,7 +520,7 @@ par_event(void)
|
|
|
f686d7 |
} else {
|
|
|
f686d7 |
int oec = ecused;
|
|
|
f686d7 |
|
|
|
f686d7 |
- if (!par_event()) {
|
|
|
f686d7 |
+ if (!par_event(endtok)) {
|
|
|
f686d7 |
ecused = oec;
|
|
|
f686d7 |
ecbuf[p] |= wc_bdata(Z_END);
|
|
|
f686d7 |
}
|
|
|
f686d7 |
diff --git a/Src/zsh.h b/Src/zsh.h
|
|
|
f686d7 |
index 207ef18..b3391ed 100644
|
|
|
f686d7 |
--- a/Src/zsh.h
|
|
|
f686d7 |
+++ b/Src/zsh.h
|
|
|
f686d7 |
@@ -395,6 +395,15 @@ enum {
|
|
|
f686d7 |
#define META_HEAPDUP 6
|
|
|
f686d7 |
#define META_HREALLOC 7
|
|
|
f686d7 |
|
|
|
f686d7 |
+/* Context to save and restore (bit fields) */
|
|
|
f686d7 |
+enum {
|
|
|
f686d7 |
+ /* History mechanism */
|
|
|
f686d7 |
+ ZCONTEXT_HIST = (1<<0),
|
|
|
f686d7 |
+ /* Lexical analyser */
|
|
|
f686d7 |
+ ZCONTEXT_LEX = (1<<1),
|
|
|
f686d7 |
+ /* Parser */
|
|
|
f686d7 |
+ ZCONTEXT_PARSE = (1<<2)
|
|
|
f686d7 |
+};
|
|
|
f686d7 |
|
|
|
f686d7 |
/**************************/
|
|
|
f686d7 |
/* Abstract types for zsh */
|
|
|
f686d7 |
diff --git a/Test/D08cmdsubst.ztst b/Test/D08cmdsubst.ztst
|
|
|
f686d7 |
index 5661b0a..a4c69a0 100644
|
|
|
f686d7 |
--- a/Test/D08cmdsubst.ztst
|
|
|
f686d7 |
+++ b/Test/D08cmdsubst.ztst
|
|
|
f686d7 |
@@ -106,3 +106,45 @@
|
|
|
f686d7 |
>34
|
|
|
f686d7 |
>"
|
|
|
f686d7 |
>" OK
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ echo $(case foo in
|
|
|
f686d7 |
+ foo)
|
|
|
f686d7 |
+ echo This test worked.
|
|
|
f686d7 |
+ ;;
|
|
|
f686d7 |
+ bar)
|
|
|
f686d7 |
+ echo This test failed in a rather bizarre way.
|
|
|
f686d7 |
+ ;;
|
|
|
f686d7 |
+ *)
|
|
|
f686d7 |
+ echo This test failed.
|
|
|
f686d7 |
+ ;;
|
|
|
f686d7 |
+ esac)
|
|
|
f686d7 |
+0:Parsing of command substitution with unmatched parentheses: case, basic
|
|
|
f686d7 |
+>This test worked.
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ echo "$(case bar in
|
|
|
f686d7 |
+ foo)
|
|
|
f686d7 |
+ echo This test spoobed.
|
|
|
f686d7 |
+ ;;
|
|
|
f686d7 |
+ bar)
|
|
|
f686d7 |
+ echo This test plurbled.
|
|
|
f686d7 |
+ ;;
|
|
|
f686d7 |
+ *)
|
|
|
f686d7 |
+ echo This test bzonked.
|
|
|
f686d7 |
+ ;;
|
|
|
f686d7 |
+ esac)"
|
|
|
f686d7 |
+0:Parsing of command substitution with unmatched parentheses: case with quotes
|
|
|
f686d7 |
+>This test plurbled.
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ echo before $(
|
|
|
f686d7 |
+ echo start; echo unpretentious |
|
|
|
f686d7 |
+ while read line; do
|
|
|
f686d7 |
+ case $line in
|
|
|
f686d7 |
+ u*)
|
|
|
f686d7 |
+ print Word began with u
|
|
|
f686d7 |
+ print and ended with a crunch
|
|
|
f686d7 |
+ ;;
|
|
|
f686d7 |
+ esac
|
|
|
f686d7 |
+ done | sed -e 's/Word/Universe/'; echo end
|
|
|
f686d7 |
+ ) after
|
|
|
f686d7 |
+0:Parsing of command substitution with ummatched parentheses: with frills
|
|
|
f686d7 |
+>before start Universe began with u and ended with a crunch end after
|
|
|
f686d7 |
--
|
|
|
f686d7 |
2.4.3
|
|
|
f686d7 |
|
|
|
f686d7 |
|
|
|
f686d7 |
From 925112048811087520954e0c739b29371eee188a Mon Sep 17 00:00:00 2001
|
|
|
f686d7 |
From: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
Date: Thu, 8 Jan 2015 21:39:26 +0000
|
|
|
f686d7 |
Subject: [PATCH 2/9] Resolves: #1338689 - better initialize parser state
|
|
|
f686d7 |
|
|
|
f686d7 |
This fix is isolated out from a huge upstream commit that includes major
|
|
|
f686d7 |
code refactoring changes together with the initialization fix actually
|
|
|
f686d7 |
needed to resolve #1338689.
|
|
|
f686d7 |
|
|
|
f686d7 |
Upstream-commit: cfd91eac0732da8ece012ca4ab051d928a85c9dd
|
|
|
f686d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
---
|
|
|
f686d7 |
Src/hist.c | 5 +++++
|
|
|
f686d7 |
Src/parse.c | 20 ++++++++++++++++++--
|
|
|
f686d7 |
2 files changed, 23 insertions(+), 2 deletions(-)
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/hist.c b/Src/hist.c
|
|
|
f686d7 |
index 561e2ac..4ba61b1 100644
|
|
|
f686d7 |
--- a/Src/hist.c
|
|
|
f686d7 |
+++ b/Src/hist.c
|
|
|
f686d7 |
@@ -804,6 +804,11 @@ strinbeg(int dohist)
|
|
|
f686d7 |
strin++;
|
|
|
f686d7 |
hbegin(dohist);
|
|
|
f686d7 |
lexinit();
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * Also initialise some variables owned by the parser but
|
|
|
f686d7 |
+ * used for communication between the parser and lexer.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ init_parse_status();
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
/* done reading a string */
|
|
|
f686d7 |
diff --git a/Src/parse.c b/Src/parse.c
|
|
|
f686d7 |
index b0a7624..b3b004b 100644
|
|
|
f686d7 |
--- a/Src/parse.c
|
|
|
f686d7 |
+++ b/Src/parse.c
|
|
|
f686d7 |
@@ -358,6 +358,21 @@ ecstrcode(char *s)
|
|
|
f686d7 |
} while (0)
|
|
|
f686d7 |
|
|
|
f686d7 |
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+mod_export void
|
|
|
f686d7 |
+init_parse_status(void)
|
|
|
f686d7 |
+{
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * These variables are currently declared by the parser, so we
|
|
|
f686d7 |
+ * initialise them here. Possibly they are more naturally declared
|
|
|
f686d7 |
+ * by the lexical anaylser; however, as they are used for signalling
|
|
|
f686d7 |
+ * between the two it's a bit ambiguous. We clear them when
|
|
|
f686d7 |
+ * using the lexical analyser for strings as well as here.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ incasepat = incond = inredir = infor = 0;
|
|
|
f686d7 |
+ incmdpos = 1;
|
|
|
f686d7 |
+}
|
|
|
f686d7 |
+
|
|
|
f686d7 |
/* Initialise wordcode buffer. */
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
@@ -372,6 +387,8 @@ init_parse(void)
|
|
|
f686d7 |
ecsoffs = ecnpats = 0;
|
|
|
f686d7 |
ecssub = 0;
|
|
|
f686d7 |
ecnfunc = 0;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ init_parse_status();
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
/* Build eprog. */
|
|
|
f686d7 |
@@ -535,9 +552,8 @@ parse_list(void)
|
|
|
f686d7 |
int c = 0;
|
|
|
f686d7 |
|
|
|
f686d7 |
tok = ENDINPUT;
|
|
|
f686d7 |
- incmdpos = 1;
|
|
|
f686d7 |
- zshlex();
|
|
|
f686d7 |
init_parse();
|
|
|
f686d7 |
+ zshlex();
|
|
|
f686d7 |
par_list(&c);
|
|
|
f686d7 |
if (tok != ENDINPUT) {
|
|
|
f686d7 |
clear_hdocs();
|
|
|
f686d7 |
--
|
|
|
f686d7 |
2.5.5
|
|
|
f686d7 |
|
|
|
f686d7 |
|
|
|
f686d7 |
From 00bc31b497525433dbaeafd3e7b92c7fe364dc8c Mon Sep 17 00:00:00 2001
|
|
|
f686d7 |
From: Peter Stephenson <pws@zsh.org>
|
|
|
f686d7 |
Date: Wed, 15 Apr 2015 10:20:06 +0100
|
|
|
f686d7 |
Subject: [PATCH 3/9] 34892 (slightly tweaked): math evaluation fix
|
|
|
f686d7 |
|
|
|
f686d7 |
An empty expression resulting from substitution includes a
|
|
|
f686d7 |
Nularg, which needs handling the same as an empty string.
|
|
|
f686d7 |
|
|
|
f686d7 |
Upstream-commit: 2ef4b38461dfb554ed2226d9de8958703bc00b98
|
|
|
f686d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
---
|
|
|
f686d7 |
Src/math.c | 15 ++++++++++++++-
|
|
|
f686d7 |
Test/C01arith.ztst | 4 ++++
|
|
|
f686d7 |
2 files changed, 18 insertions(+), 1 deletion(-)
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/math.c b/Src/math.c
|
|
|
f686d7 |
index e90d6a5..d6db7d3 100644
|
|
|
f686d7 |
--- a/Src/math.c
|
|
|
f686d7 |
+++ b/Src/math.c
|
|
|
f686d7 |
@@ -1330,7 +1330,7 @@ matheval(char *s)
|
|
|
f686d7 |
if (!mlevel)
|
|
|
f686d7 |
outputradix = 0;
|
|
|
f686d7 |
|
|
|
f686d7 |
- if (!*s) {
|
|
|
f686d7 |
+ if (!*s || *s == Nularg) {
|
|
|
f686d7 |
x.type = MN_INTEGER;
|
|
|
f686d7 |
x.u.l = 0;
|
|
|
f686d7 |
return x;
|
|
|
f686d7 |
@@ -1358,6 +1358,19 @@ mathevalarg(char *s, char **ss)
|
|
|
f686d7 |
mnumber x;
|
|
|
f686d7 |
int xmtok = mtok;
|
|
|
f686d7 |
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * At this entry point we don't allow an empty expression,
|
|
|
f686d7 |
+ * whereas we do with matheval(). I'm not sure if this
|
|
|
f686d7 |
+ * difference is deliberate, but it does mean that e.g.
|
|
|
f686d7 |
+ * $array[$ind] where ind hasn't been set produces an error,
|
|
|
f686d7 |
+ * which is probably safe.
|
|
|
f686d7 |
+ *
|
|
|
f686d7 |
+ * To avoid a more opaque error further in, bail out here.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ if (!*s || *s == Nularg) {
|
|
|
f686d7 |
+ zerr("bad math expression: empty string");
|
|
|
f686d7 |
+ return (zlong)0;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
x = mathevall(s, MPREC_ARG, ss);
|
|
|
f686d7 |
if (mtok == COMMA)
|
|
|
f686d7 |
(*ss)--;
|
|
|
f686d7 |
diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst
|
|
|
f686d7 |
index 02d1519..33b03ef 100644
|
|
|
f686d7 |
--- a/Test/C01arith.ztst
|
|
|
f686d7 |
+++ b/Test/C01arith.ztst
|
|
|
f686d7 |
@@ -243,3 +243,7 @@
|
|
|
f686d7 |
>6000000
|
|
|
f686d7 |
>5000
|
|
|
f686d7 |
>255
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ print $((`:`))
|
|
|
f686d7 |
+0:Null string in arithmetic evaluation after command substitution
|
|
|
f686d7 |
+>0
|
|
|
f686d7 |
--
|
|
|
f686d7 |
2.4.6
|
|
|
f686d7 |
|
|
|
f686d7 |
|
|
|
f686d7 |
From 0c1450a286e578a1cfe266bf743faf2f0719f85b Mon Sep 17 00:00:00 2001
|
|
|
f686d7 |
From: "Barton E. Schaefer" <schaefer@zsh.org>
|
|
|
f686d7 |
Date: Wed, 29 Jul 2015 22:36:45 -0700
|
|
|
f686d7 |
Subject: [PATCH 4/9] 35953: fix handling of command substitution in math
|
|
|
f686d7 |
context
|
|
|
f686d7 |
|
|
|
f686d7 |
Upstream-commit: c0a80171ee615b52a15a6fc8efe83c2bb53451d2
|
|
|
f686d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
---
|
|
|
f686d7 |
Src/lex.c | 6 +++++-
|
|
|
f686d7 |
Test/A01grammar.ztst | 6 ++++++
|
|
|
f686d7 |
2 files changed, 11 insertions(+), 1 deletion(-)
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/lex.c b/Src/lex.c
|
|
|
f686d7 |
index bcceda6..f43b92b 100644
|
|
|
f686d7 |
--- a/Src/lex.c
|
|
|
f686d7 |
+++ b/Src/lex.c
|
|
|
f686d7 |
@@ -1541,7 +1541,7 @@ dquote_parse(char endchar, int sub)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
int pct = 0, brct = 0, bct = 0, intick = 0, err = 0;
|
|
|
f686d7 |
int c;
|
|
|
f686d7 |
- int math = endchar == ')' || endchar == ']';
|
|
|
f686d7 |
+ int math = endchar == ')' || endchar == ']' || infor;
|
|
|
f686d7 |
int zlemath = math && zlemetacs > zlemetall + addedx - inbufct;
|
|
|
f686d7 |
|
|
|
f686d7 |
while (((c = hgetc()) != endchar || bct ||
|
|
|
f686d7 |
@@ -2004,7 +2004,9 @@ skipcomm(void)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
char *new_tokstr, *new_bptr = bptr_raw;
|
|
|
f686d7 |
int new_len, new_bsiz, new_lexstop, new_lex_add_raw;
|
|
|
f686d7 |
+ int save_infor = infor;
|
|
|
f686d7 |
|
|
|
f686d7 |
+ infor = 0;
|
|
|
f686d7 |
cmdpush(CS_CMDSUBST);
|
|
|
f686d7 |
SETPARBEGIN
|
|
|
f686d7 |
add(Inpar);
|
|
|
f686d7 |
@@ -2054,6 +2056,7 @@ skipcomm(void)
|
|
|
f686d7 |
len_raw = new_len;
|
|
|
f686d7 |
bptr_raw = new_bptr;
|
|
|
f686d7 |
lex_add_raw = new_lex_add_raw;
|
|
|
f686d7 |
+ dbparens = 0; /* restored by zcontext_restore_partial() */
|
|
|
f686d7 |
|
|
|
f686d7 |
if (!parse_event(OUTPAR) || tok != OUTPAR)
|
|
|
f686d7 |
lexstop = 1;
|
|
|
f686d7 |
@@ -2105,6 +2108,7 @@ skipcomm(void)
|
|
|
f686d7 |
if (!lexstop)
|
|
|
f686d7 |
SETPAREND
|
|
|
f686d7 |
cmdpop();
|
|
|
f686d7 |
+ infor = save_infor;
|
|
|
f686d7 |
|
|
|
f686d7 |
return lexstop;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
|
|
|
f686d7 |
index f04ddda..584ebd6 100644
|
|
|
f686d7 |
--- a/Test/A01grammar.ztst
|
|
|
f686d7 |
+++ b/Test/A01grammar.ztst
|
|
|
f686d7 |
@@ -169,6 +169,12 @@
|
|
|
f686d7 |
>1
|
|
|
f686d7 |
>2
|
|
|
f686d7 |
|
|
|
f686d7 |
+ for (( $(true); ; )); do break; done
|
|
|
f686d7 |
+ for (( ; $(true); )); do break; done
|
|
|
f686d7 |
+ for (( ; ; $(true) )); do break; done
|
|
|
f686d7 |
+ for (( ; $((1)); )); do break; done
|
|
|
f686d7 |
+0:regression test, nested cmdsubst in arithmetic `for' loop
|
|
|
f686d7 |
+
|
|
|
f686d7 |
for keyvar valvar in key1 val1 key2 val2; do
|
|
|
f686d7 |
print key=$keyvar val=$valvar
|
|
|
f686d7 |
done
|
|
|
f686d7 |
--
|
|
|
f686d7 |
2.4.6
|
|
|
f686d7 |
|
|
|
f686d7 |
|
|
|
f686d7 |
From 821815bd9c24a84d8bb5796732ab6144b35e7d27 Mon Sep 17 00:00:00 2001
|
|
|
f686d7 |
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
|
|
|
f686d7 |
Date: Sat, 10 Jan 2015 20:28:57 +0000
|
|
|
f686d7 |
Subject: [PATCH 5/9] 34220: new $(...) handling needs to back up over alias
|
|
|
f686d7 |
expansion
|
|
|
f686d7 |
|
|
|
f686d7 |
Upstream-commit: 3b32abafdb019cfb8f29908bc3d148e01518981d
|
|
|
f686d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
---
|
|
|
f686d7 |
Src/input.c | 6 ++++++
|
|
|
f686d7 |
1 file changed, 6 insertions(+)
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/input.c b/Src/input.c
|
|
|
f686d7 |
index 1579762..5b782dc 100644
|
|
|
f686d7 |
--- a/Src/input.c
|
|
|
f686d7 |
+++ b/Src/input.c
|
|
|
f686d7 |
@@ -532,6 +532,12 @@ inpush(char *str, int flags, Alias inalias)
|
|
|
f686d7 |
static void
|
|
|
f686d7 |
inpoptop(void)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
+ if (!lexstop) {
|
|
|
f686d7 |
+ inbufflags &= ~INP_ALCONT;
|
|
|
f686d7 |
+ while (inbufptr > inbuf)
|
|
|
f686d7 |
+ inungetc(inbufptr[-1]);
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+
|
|
|
f686d7 |
if (inbuf && (inbufflags & INP_FREE))
|
|
|
f686d7 |
free(inbuf);
|
|
|
f686d7 |
|
|
|
f686d7 |
--
|
|
|
f686d7 |
2.4.6
|
|
|
f686d7 |
|
|
|
f686d7 |
|
|
|
f686d7 |
From 1c731b7d1178a2623aa1b986f38a7decebf2c993 Mon Sep 17 00:00:00 2001
|
|
|
f686d7 |
From: Peter Stephenson <pws@zsh.org>
|
|
|
f686d7 |
Date: Fri, 16 Jan 2015 13:20:05 +0000
|
|
|
f686d7 |
Subject: [PATCH 6/9] 34304: improve use of new cmd subst in completion
|
|
|
f686d7 |
|
|
|
f686d7 |
Upstream-commit: db05cc51fa2298cf128e480d3ac8e5373029f6b9
|
|
|
f686d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
---
|
|
|
f686d7 |
Src/lex.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
|
|
|
f686d7 |
1 file changed, 103 insertions(+), 10 deletions(-)
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/lex.c b/Src/lex.c
|
|
|
f686d7 |
index f43b92b..45c1117 100644
|
|
|
f686d7 |
--- a/Src/lex.c
|
|
|
f686d7 |
+++ b/Src/lex.c
|
|
|
f686d7 |
@@ -88,6 +88,12 @@ int inalmore;
|
|
|
f686d7 |
int nocorrect;
|
|
|
f686d7 |
|
|
|
f686d7 |
/*
|
|
|
f686d7 |
+ * TBD: the following exported variables are part of the non-interface
|
|
|
f686d7 |
+ * with ZLE for completion. They are poorly named and the whole
|
|
|
f686d7 |
+ * scheme is incredibly brittle. One piece of robustness is applied:
|
|
|
f686d7 |
+ * the variables are only set if LEXFLAGS_ZLE is set. Improvements
|
|
|
f686d7 |
+ * should therefore concentrate on areas with this flag set.
|
|
|
f686d7 |
+ *
|
|
|
f686d7 |
* Cursor position and line length in zle when the line is
|
|
|
f686d7 |
* metafied for access from the main shell.
|
|
|
f686d7 |
*/
|
|
|
f686d7 |
@@ -111,6 +117,16 @@ mod_export int addedx;
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
mod_export int wb, we;
|
|
|
f686d7 |
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+mod_export int wordbeg;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+mod_export int parbegin;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+mod_export int parend;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+
|
|
|
f686d7 |
/* 1 if aliases should not be expanded */
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
@@ -132,15 +148,6 @@ mod_export int noaliases;
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
mod_export int lexflags;
|
|
|
f686d7 |
|
|
|
f686d7 |
-/**/
|
|
|
f686d7 |
-mod_export int wordbeg;
|
|
|
f686d7 |
-
|
|
|
f686d7 |
-/**/
|
|
|
f686d7 |
-mod_export int parbegin;
|
|
|
f686d7 |
-
|
|
|
f686d7 |
-/**/
|
|
|
f686d7 |
-mod_export int parend;
|
|
|
f686d7 |
-
|
|
|
f686d7 |
/* don't recognize comments */
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
@@ -791,7 +798,8 @@ gettok(void)
|
|
|
f686d7 |
if (lexstop)
|
|
|
f686d7 |
return (errflag) ? LEXERR : ENDINPUT;
|
|
|
f686d7 |
isfirstln = 0;
|
|
|
f686d7 |
- wordbeg = inbufct - (qbang && c == bangchar);
|
|
|
f686d7 |
+ if ((lexflags & LEXFLAGS_ZLE))
|
|
|
f686d7 |
+ wordbeg = inbufct - (qbang && c == bangchar);
|
|
|
f686d7 |
hwbegin(-1-(qbang && c == bangchar));
|
|
|
f686d7 |
/* word includes the last character read and possibly \ before ! */
|
|
|
f686d7 |
if (dbparens) {
|
|
|
f686d7 |
@@ -2002,6 +2010,78 @@ zshlex_raw_back(void)
|
|
|
f686d7 |
static int
|
|
|
f686d7 |
skipcomm(void)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
+#ifdef ZSH_OLD_SKIPCOMM
|
|
|
f686d7 |
+ int pct = 1, c, start = 1;
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+ cmdpush(CS_CMDSUBST);
|
|
|
f686d7 |
+ SETPARBEGIN
|
|
|
f686d7 |
+ c = Inpar;
|
|
|
f686d7 |
+ do {
|
|
|
f686d7 |
+ int iswhite;
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ c = hgetc();
|
|
|
f686d7 |
+ if (itok(c) || lexstop)
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
+ iswhite = inblank(c);
|
|
|
f686d7 |
+ switch (c) {
|
|
|
f686d7 |
+ case '(':
|
|
|
f686d7 |
+ pct++;
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
+ case ')':
|
|
|
f686d7 |
+ pct--;
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
+ case '\\':
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ c = hgetc();
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
+ case '\'': {
|
|
|
f686d7 |
+ int strquote = lexbuf.ptr[-1] == '$';
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ STOPHIST
|
|
|
f686d7 |
+ while ((c = hgetc()) != '\'' && !lexstop) {
|
|
|
f686d7 |
+ if (c == '\\' && strquote) {
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ c = hgetc();
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ ALLOWHIST
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ case '\"':
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ while ((c = hgetc()) != '\"' && !lexstop)
|
|
|
f686d7 |
+ if (c == '\\') {
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ add(hgetc());
|
|
|
f686d7 |
+ } else
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
+ case '`':
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ while ((c = hgetc()) != '`' && !lexstop)
|
|
|
f686d7 |
+ if (c == '\\')
|
|
|
f686d7 |
+ add(c), add(hgetc());
|
|
|
f686d7 |
+ else
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
+ case '#':
|
|
|
f686d7 |
+ if (start) {
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ while ((c = hgetc()) != '\n' && !lexstop)
|
|
|
f686d7 |
+ add(c);
|
|
|
f686d7 |
+ iswhite = 1;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ break;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ start = iswhite;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
+ while (pct);
|
|
|
f686d7 |
+ if (!lexstop)
|
|
|
f686d7 |
+ SETPAREND
|
|
|
f686d7 |
+ cmdpop();
|
|
|
f686d7 |
+ return lexstop;
|
|
|
f686d7 |
+#else
|
|
|
f686d7 |
char *new_tokstr, *new_bptr = bptr_raw;
|
|
|
f686d7 |
int new_len, new_bsiz, new_lexstop, new_lex_add_raw;
|
|
|
f686d7 |
int save_infor = infor;
|
|
|
f686d7 |
@@ -2057,6 +2137,18 @@ skipcomm(void)
|
|
|
f686d7 |
bptr_raw = new_bptr;
|
|
|
f686d7 |
lex_add_raw = new_lex_add_raw;
|
|
|
f686d7 |
dbparens = 0; /* restored by zcontext_restore_partial() */
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * Don't do any ZLE specials down here: they're only needed
|
|
|
f686d7 |
+ * when we return the string from the recursive parse.
|
|
|
f686d7 |
+ * (TBD: this probably means we should be initialising lexflags
|
|
|
f686d7 |
+ * more consistently.)
|
|
|
f686d7 |
+ *
|
|
|
f686d7 |
+ * Note that in that case we're still using the ZLE line reading
|
|
|
f686d7 |
+ * function at the history layer --- this is consistent with the
|
|
|
f686d7 |
+ * intention of maintaining the history and input layers across
|
|
|
f686d7 |
+ * the recursive parsing.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ lexflags &= ~LEXFLAGS_ZLE;
|
|
|
f686d7 |
|
|
|
f686d7 |
if (!parse_event(OUTPAR) || tok != OUTPAR)
|
|
|
f686d7 |
lexstop = 1;
|
|
|
f686d7 |
@@ -2111,4 +2203,5 @@ skipcomm(void)
|
|
|
f686d7 |
infor = save_infor;
|
|
|
f686d7 |
|
|
|
f686d7 |
return lexstop;
|
|
|
f686d7 |
+#endif
|
|
|
f686d7 |
}
|
|
|
f686d7 |
--
|
|
|
f686d7 |
2.5.5
|
|
|
f686d7 |
|
|
|
f686d7 |
|
|
|
f686d7 |
From ad64470d3ea4190cd854aab2bc0f8d01ec6aef11 Mon Sep 17 00:00:00 2001
|
|
|
f686d7 |
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
|
|
|
f686d7 |
Date: Fri, 16 Jan 2015 20:12:40 +0000
|
|
|
f686d7 |
Subject: [PATCH 7/9] 32413: turn off history word marking in cmd subst
|
|
|
f686d7 |
|
|
|
f686d7 |
Upstream-commit: f2a2f28f7bde196cd1fa205ac0c20336046cf2cf
|
|
|
f686d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
---
|
|
|
f686d7 |
Src/hist.c | 22 ++++++++++++++++++++--
|
|
|
f686d7 |
Src/lex.c | 2 ++
|
|
|
f686d7 |
2 files changed, 22 insertions(+), 2 deletions(-)
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/hist.c b/Src/hist.c
|
|
|
f686d7 |
index 561e2ac..e29a566 100644
|
|
|
f686d7 |
--- a/Src/hist.c
|
|
|
f686d7 |
+++ b/Src/hist.c
|
|
|
f686d7 |
@@ -131,6 +131,8 @@ mod_export int hist_skip_flags;
|
|
|
f686d7 |
/* Bits of histactive variable */
|
|
|
f686d7 |
#define HA_ACTIVE (1<<0) /* History mechanism is active */
|
|
|
f686d7 |
#define HA_NOINC (1<<1) /* Don't store, curhist not incremented */
|
|
|
f686d7 |
+#define HA_INWORD (1<<2) /* We're inside a word, don't add
|
|
|
f686d7 |
+ start and end markers */
|
|
|
f686d7 |
|
|
|
f686d7 |
/* Array of word beginnings and endings in current history line. */
|
|
|
f686d7 |
|
|
|
f686d7 |
@@ -219,6 +221,22 @@ static int histsave_stack_pos = 0;
|
|
|
f686d7 |
|
|
|
f686d7 |
static zlong histfile_linect;
|
|
|
f686d7 |
|
|
|
f686d7 |
+/*
|
|
|
f686d7 |
+ * Mark that the current level of history is or is not
|
|
|
f686d7 |
+ * within a word, whatever turns up. This is used for nested
|
|
|
f686d7 |
+ * parsing of substitutions.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+/**/
|
|
|
f686d7 |
+void
|
|
|
f686d7 |
+hist_in_word(int yesno)
|
|
|
f686d7 |
+{
|
|
|
f686d7 |
+ if (yesno)
|
|
|
f686d7 |
+ histactive |= HA_INWORD;
|
|
|
f686d7 |
+ else
|
|
|
f686d7 |
+ histactive &= ~HA_INWORD;
|
|
|
f686d7 |
+}
|
|
|
f686d7 |
+
|
|
|
f686d7 |
/* add a character to the current history word */
|
|
|
f686d7 |
|
|
|
f686d7 |
static void
|
|
|
f686d7 |
@@ -1329,7 +1347,7 @@ int hwgetword = -1;
|
|
|
f686d7 |
void
|
|
|
f686d7 |
ihwbegin(int offset)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
- if (stophist == 2)
|
|
|
f686d7 |
+ if (stophist == 2 || (histactive & HA_INWORD))
|
|
|
f686d7 |
return;
|
|
|
f686d7 |
if (chwordpos%2)
|
|
|
f686d7 |
chwordpos--; /* make sure we're on a word start, not end */
|
|
|
f686d7 |
@@ -1349,7 +1367,7 @@ ihwbegin(int offset)
|
|
|
f686d7 |
void
|
|
|
f686d7 |
ihwend(void)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
- if (stophist == 2)
|
|
|
f686d7 |
+ if (stophist == 2 || (histactive & HA_INWORD))
|
|
|
f686d7 |
return;
|
|
|
f686d7 |
if (chwordpos%2 && chline) {
|
|
|
f686d7 |
/* end of word reached and we've already begun a word */
|
|
|
f686d7 |
diff --git a/Src/lex.c b/Src/lex.c
|
|
|
f686d7 |
index f43b92b..f1aa85d 100644
|
|
|
f686d7 |
--- a/Src/lex.c
|
|
|
f686d7 |
+++ b/Src/lex.c
|
|
|
f686d7 |
@@ -2114,6 +2114,7 @@ skipcomm(void)
|
|
|
f686d7 |
new_bsiz = bsiz;
|
|
|
f686d7 |
|
|
|
f686d7 |
lexsave_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
|
|
|
f686d7 |
+ hist_in_word(1);
|
|
|
f686d7 |
} else {
|
|
|
f686d7 |
/*
|
|
|
f686d7 |
* Set up for nested command subsitution, however
|
|
|
f686d7 |
@@ -2195,6 +2196,7 @@ skipcomm(void)
|
|
|
f686d7 |
len = new_len;
|
|
|
f686d7 |
bsiz = new_bsiz;
|
|
|
f686d7 |
lexstop = new_lexstop;
|
|
|
f686d7 |
+ hist_in_word(0);
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
if (!lexstop)
|
|
|
f686d7 |
--
|
|
|
f686d7 |
2.5.5
|
|
|
f686d7 |
|
|
|
f686d7 |
|
|
|
f686d7 |
From 22b063c5f2bb3350c856215e436a62d25440e605 Mon Sep 17 00:00:00 2001
|
|
|
f686d7 |
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
|
|
|
f686d7 |
Date: Sun, 18 Jan 2015 16:43:26 +0000
|
|
|
f686d7 |
Subject: [PATCH 8/9] 34319: fix alias expansion in history for command
|
|
|
f686d7 |
substitution
|
|
|
f686d7 |
|
|
|
f686d7 |
Upstream-commit: e34ce85151dcd5ac698e116a6742d481ff64ae2c
|
|
|
f686d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
---
|
|
|
f686d7 |
Src/hist.c | 26 ++++++++++++++++++++------
|
|
|
f686d7 |
1 file changed, 20 insertions(+), 6 deletions(-)
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/hist.c b/Src/hist.c
|
|
|
f686d7 |
index e29a566..08763fe 100644
|
|
|
f686d7 |
--- a/Src/hist.c
|
|
|
f686d7 |
+++ b/Src/hist.c
|
|
|
f686d7 |
@@ -243,7 +243,16 @@ static void
|
|
|
f686d7 |
ihwaddc(int c)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
/* Only if history line exists and lexing has not finished. */
|
|
|
f686d7 |
- if (chline && !(errflag || lexstop)) {
|
|
|
f686d7 |
+ if (chline && !(errflag || lexstop) &&
|
|
|
f686d7 |
+ /*
|
|
|
f686d7 |
+ * If we're reading inside a word for command substitution
|
|
|
f686d7 |
+ * we allow the lexer to expand aliases but don't deal
|
|
|
f686d7 |
+ * with them here. Note matching code in ihungetc().
|
|
|
f686d7 |
+ * TBD: it might be neater to deal with all aliases in this
|
|
|
f686d7 |
+ * fashion as we never need the expansion in the history
|
|
|
f686d7 |
+ * line, only in the lexer and above.
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
+ !((histactive & HA_INWORD) && (inbufflags & INP_ALIAS))) {
|
|
|
f686d7 |
/* Quote un-expanded bangs in the history line. */
|
|
|
f686d7 |
if (c == bangchar && stophist < 2 && qbang)
|
|
|
f686d7 |
/* If qbang is not set, we do not escape this bangchar as it's *
|
|
|
f686d7 |
@@ -798,11 +807,16 @@ ihungetc(int c)
|
|
|
f686d7 |
zlemetall--;
|
|
|
f686d7 |
exlast++;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
- DPUTS(hptr <= chline, "BUG: hungetc attempted at buffer start");
|
|
|
f686d7 |
- hptr--;
|
|
|
f686d7 |
- DPUTS(*hptr != (char) c, "BUG: wrong character in hungetc() ");
|
|
|
f686d7 |
- qbang = (c == bangchar && stophist < 2 &&
|
|
|
f686d7 |
- hptr > chline && hptr[-1] == '\\');
|
|
|
f686d7 |
+ if (!(histactive & HA_INWORD) || !(inbufflags & INP_ALIAS)) {
|
|
|
f686d7 |
+ DPUTS(hptr <= chline, "BUG: hungetc attempted at buffer start");
|
|
|
f686d7 |
+ hptr--;
|
|
|
f686d7 |
+ DPUTS(*hptr != (char) c, "BUG: wrong character in hungetc() ");
|
|
|
f686d7 |
+ qbang = (c == bangchar && stophist < 2 &&
|
|
|
f686d7 |
+ hptr > chline && hptr[-1] == '\\');
|
|
|
f686d7 |
+ } else {
|
|
|
f686d7 |
+ /* No active bangs in aliases */
|
|
|
f686d7 |
+ qbang = 0;
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
if (doit)
|
|
|
f686d7 |
inungetc(c);
|
|
|
f686d7 |
if (!qbang)
|
|
|
f686d7 |
--
|
|
|
f686d7 |
2.5.5
|
|
|
f686d7 |
|
|
|
f686d7 |
|
|
|
f686d7 |
From 155587d13060e4c7c9bbd61b7cc0a6dd17922d56 Mon Sep 17 00:00:00 2001
|
|
|
f686d7 |
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
|
|
|
f686d7 |
Date: Sun, 18 Jan 2015 22:38:57 +0000
|
|
|
f686d7 |
Subject: [PATCH 9/9] 34322: bug with interface to parsestr() etc.
|
|
|
f686d7 |
|
|
|
f686d7 |
Was showing up in places like ${(e)...} where command substitution
|
|
|
f686d7 |
could reallocate the token string, but actually there was never any
|
|
|
f686d7 |
guarantee that the lexer wouldn't do that, so this was always
|
|
|
f686d7 |
a bit iffy.
|
|
|
f686d7 |
|
|
|
f686d7 |
Upstream-commit: c6c9f5daf2e196e6ab7346dfbf5f5166a1d87f0c
|
|
|
f686d7 |
Signed-off-by: Kamil Dudka <kdudka@redhat.com>
|
|
|
f686d7 |
---
|
|
|
f686d7 |
Src/Zle/compctl.c | 4 ++--
|
|
|
f686d7 |
Src/Zle/compresult.c | 3 ++-
|
|
|
f686d7 |
Src/exec.c | 9 +++++----
|
|
|
f686d7 |
Src/init.c | 11 +++++++----
|
|
|
f686d7 |
Src/lex.c | 30 +++++++++++++++++++++---------
|
|
|
f686d7 |
Src/params.c | 3 ++-
|
|
|
f686d7 |
Src/prompt.c | 2 +-
|
|
|
f686d7 |
Src/subst.c | 8 +++++---
|
|
|
f686d7 |
Src/utils.c | 2 +-
|
|
|
f686d7 |
Test/D04parameter.ztst | 7 +++++++
|
|
|
f686d7 |
10 files changed, 53 insertions(+), 26 deletions(-)
|
|
|
f686d7 |
|
|
|
f686d7 |
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
|
|
|
f686d7 |
index 0143370..5d67137 100644
|
|
|
f686d7 |
--- a/Src/Zle/compctl.c
|
|
|
f686d7 |
+++ b/Src/Zle/compctl.c
|
|
|
f686d7 |
@@ -3854,7 +3854,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|
|
f686d7 |
yaptr = get_user_var(uv);
|
|
|
f686d7 |
if ((tt = cc->explain)) {
|
|
|
f686d7 |
tt = dupstring(tt);
|
|
|
f686d7 |
- if ((cc->mask & CC_EXPANDEXPL) && !parsestr(tt)) {
|
|
|
f686d7 |
+ if ((cc->mask & CC_EXPANDEXPL) && !parsestr(&tt)) {
|
|
|
f686d7 |
singsub(&tt;;
|
|
|
f686d7 |
untokenize(tt);
|
|
|
f686d7 |
}
|
|
|
f686d7 |
@@ -3874,7 +3874,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
|
|
|
f686d7 |
}
|
|
|
f686d7 |
} else if ((tt = cc->explain)) {
|
|
|
f686d7 |
tt = dupstring(tt);
|
|
|
f686d7 |
- if ((cc->mask & CC_EXPANDEXPL) && !parsestr(tt)) {
|
|
|
f686d7 |
+ if ((cc->mask & CC_EXPANDEXPL) && !parsestr(&tt)) {
|
|
|
f686d7 |
singsub(&tt;;
|
|
|
f686d7 |
untokenize(tt);
|
|
|
f686d7 |
}
|
|
|
f686d7 |
diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c
|
|
|
f686d7 |
index c0e5ff3..69d066c 100644
|
|
|
f686d7 |
--- a/Src/Zle/compresult.c
|
|
|
f686d7 |
+++ b/Src/Zle/compresult.c
|
|
|
f686d7 |
@@ -1090,7 +1090,8 @@ do_single(Cmatch m)
|
|
|
f686d7 |
}
|
|
|
f686d7 |
if (tryit) {
|
|
|
f686d7 |
noerrs = 1;
|
|
|
f686d7 |
- parsestr(p);
|
|
|
f686d7 |
+ p = dupstring(p);
|
|
|
f686d7 |
+ parsestr(&p);
|
|
|
f686d7 |
singsub(&p);
|
|
|
f686d7 |
errflag = 0;
|
|
|
f686d7 |
noerrs = ne;
|
|
|
f686d7 |
diff --git a/Src/exec.c b/Src/exec.c
|
|
|
f686d7 |
index 7817a64..27e235f 100644
|
|
|
f686d7 |
--- a/Src/exec.c
|
|
|
f686d7 |
+++ b/Src/exec.c
|
|
|
f686d7 |
@@ -3631,17 +3631,18 @@ gethere(char **strp, int typ)
|
|
|
f686d7 |
*bptr++ = '\n';
|
|
|
f686d7 |
}
|
|
|
f686d7 |
*t = '\0';
|
|
|
f686d7 |
+ s = buf;
|
|
|
f686d7 |
+ buf = dupstring(buf);
|
|
|
f686d7 |
+ zfree(s, bsiz);
|
|
|
f686d7 |
if (!qt) {
|
|
|
f686d7 |
int ef = errflag;
|
|
|
f686d7 |
|
|
|
f686d7 |
- parsestr(buf);
|
|
|
f686d7 |
+ parsestr(&buf;;
|
|
|
f686d7 |
|
|
|
f686d7 |
if (!errflag)
|
|
|
f686d7 |
errflag = ef;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
- s = dupstring(buf);
|
|
|
f686d7 |
- zfree(buf, bsiz);
|
|
|
f686d7 |
- return s;
|
|
|
f686d7 |
+ return buf;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
/* open here string fd */
|
|
|
f686d7 |
diff --git a/Src/init.c b/Src/init.c
|
|
|
f686d7 |
index 78f171d..485fb32 100644
|
|
|
f686d7 |
--- a/Src/init.c
|
|
|
f686d7 |
+++ b/Src/init.c
|
|
|
f686d7 |
@@ -1143,10 +1143,13 @@ run_init_scripts(void)
|
|
|
f686d7 |
if (islogin)
|
|
|
f686d7 |
sourcehome(".profile");
|
|
|
f686d7 |
noerrs = 2;
|
|
|
f686d7 |
- if (s && !parsestr(s)) {
|
|
|
f686d7 |
- singsub(&s);
|
|
|
f686d7 |
- noerrs = 0;
|
|
|
f686d7 |
- source(s);
|
|
|
f686d7 |
+ if (s) {
|
|
|
f686d7 |
+ s = dupstring(s);
|
|
|
f686d7 |
+ if (!parsestr(&s)) {
|
|
|
f686d7 |
+ singsub(&s);
|
|
|
f686d7 |
+ noerrs = 0;
|
|
|
f686d7 |
+ source(s);
|
|
|
f686d7 |
+ }
|
|
|
f686d7 |
}
|
|
|
f686d7 |
noerrs = 0;
|
|
|
f686d7 |
} else
|
|
|
f686d7 |
diff --git a/Src/lex.c b/Src/lex.c
|
|
|
f686d7 |
index b8fe332..fa920bd 100644
|
|
|
f686d7 |
--- a/Src/lex.c
|
|
|
f686d7 |
+++ b/Src/lex.c
|
|
|
f686d7 |
@@ -1693,17 +1693,27 @@ dquote_parse(char endchar, int sub)
|
|
|
f686d7 |
return err;
|
|
|
f686d7 |
}
|
|
|
f686d7 |
|
|
|
f686d7 |
-/* Tokenize a string given in s. Parsing is done as in double *
|
|
|
f686d7 |
- * quotes. This is usually called before singsub(). */
|
|
|
f686d7 |
+/*
|
|
|
f686d7 |
+ * Tokenize a string given in s. Parsing is done as in double
|
|
|
f686d7 |
+ * quotes. This is usually called before singsub().
|
|
|
f686d7 |
+ *
|
|
|
f686d7 |
+ * parsestr() is noisier, reporting an error if the parse failed.
|
|
|
f686d7 |
+ *
|
|
|
f686d7 |
+ * On entry, *s must point to a string allocated from the stack of
|
|
|
f686d7 |
+ * exactly the right length, i.e. strlen(*s) + 1, as the string
|
|
|
f686d7 |
+ * is used as the lexical token string whose memory management
|
|
|
f686d7 |
+ * demands this. Usually the input string will therefore be
|
|
|
f686d7 |
+ * the result of an immediately preceding dupstring().
|
|
|
f686d7 |
+ */
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
mod_export int
|
|
|
f686d7 |
-parsestr(char *s)
|
|
|
f686d7 |
+parsestr(char **s)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
int err;
|
|
|
f686d7 |
|
|
|
f686d7 |
if ((err = parsestrnoerr(s))) {
|
|
|
f686d7 |
- untokenize(s);
|
|
|
f686d7 |
+ untokenize(*s);
|
|
|
f686d7 |
if (err > 32 && err < 127)
|
|
|
f686d7 |
zerr("parse error near `%c'", err);
|
|
|
f686d7 |
else
|
|
|
f686d7 |
@@ -1714,18 +1724,20 @@ parsestr(char *s)
|
|
|
f686d7 |
|
|
|
f686d7 |
/**/
|
|
|
f686d7 |
mod_export int
|
|
|
f686d7 |
-parsestrnoerr(char *s)
|
|
|
f686d7 |
+parsestrnoerr(char **s)
|
|
|
f686d7 |
{
|
|
|
f686d7 |
- int l = strlen(s), err;
|
|
|
f686d7 |
+ int l = strlen(*s), err;
|
|
|
f686d7 |
|
|
|
f686d7 |
lexsave();
|
|
|
f686d7 |
- untokenize(s);
|
|
|
f686d7 |
- inpush(dupstring(s), 0, NULL);
|
|
|
f686d7 |
+ untokenize(*s);
|
|
|
f686d7 |
+ inpush(dupstring(*s), 0, NULL);
|
|
|
f686d7 |
strinbeg(0);
|
|
|
f686d7 |
len = 0;
|
|
|
f686d7 |
- bptr = tokstr = s;
|
|
|
f686d7 |
+ bptr = tokstr = *s;
|
|
|
f686d7 |
bsiz = l + 1;
|
|
|
f686d7 |
err = dquote_parse('\0', 1);
|
|
|
f686d7 |
+ if (tokstr)
|
|
|
f686d7 |
+ *s = tokstr;
|
|
|
f686d7 |
*bptr = '\0';
|
|
|
f686d7 |
strinend();
|
|
|
f686d7 |
inpop();
|
|
|
f686d7 |
diff --git a/Src/params.c b/Src/params.c
|
|
|
f686d7 |
index babf6f2..f7551b2 100644
|
|
|
f686d7 |
--- a/Src/params.c
|
|
|
f686d7 |
+++ b/Src/params.c
|
|
|
f686d7 |
@@ -1241,7 +1241,8 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
|
|
|
f686d7 |
if (ishash && (keymatch || !rev))
|
|
|
f686d7 |
remnulargs(s);
|
|
|
f686d7 |
if (needtok) {
|
|
|
f686d7 |
- if (parsestr(s))
|
|
|
f686d7 |
+ s = dupstring(s);
|
|
|
f686d7 |
+ if (parsestr(&s))
|
|
|
f686d7 |
return 0;
|
|
|
f686d7 |
singsub(&s);
|
|
|
f686d7 |
} else if (rev)
|
|
|
f686d7 |
diff --git a/Src/prompt.c b/Src/prompt.c
|
|
|
f686d7 |
index e51ce24..290f227 100644
|
|
|
f686d7 |
--- a/Src/prompt.c
|
|
|
f686d7 |
+++ b/Src/prompt.c
|
|
|
f686d7 |
@@ -183,7 +183,7 @@ promptexpand(char *s, int ns, char *rs, char *Rs, unsigned int *txtchangep)
|
|
|
f686d7 |
int oldval = lastval;
|
|
|
f686d7 |
|
|
|
f686d7 |
s = dupstring(s);
|
|
|
f686d7 |
- if (!parsestr(s))
|
|
|
f686d7 |
+ if (!parsestr(&s))
|
|
|
f686d7 |
singsub(&s);
|
|
|
f686d7 |
/*
|
|
|
f686d7 |
* We don't need the special Nularg hack here and we're
|
|
|
f686d7 |
diff --git a/Src/subst.c b/Src/subst.c
|
|
|
f686d7 |
index a4df256..dcffe2f 100644
|
|
|
f686d7 |
--- a/Src/subst.c
|
|
|
f686d7 |
+++ b/Src/subst.c
|
|
|
f686d7 |
@@ -1306,7 +1306,7 @@ get_intarg(char **s, int *delmatchp)
|
|
|
f686d7 |
p = dupstring(*s + arglen);
|
|
|
f686d7 |
*s = t + arglen;
|
|
|
f686d7 |
*t = sav;
|
|
|
f686d7 |
- if (parsestr(p))
|
|
|
f686d7 |
+ if (parsestr(&p))
|
|
|
f686d7 |
return -1;
|
|
|
f686d7 |
singsub(&p);
|
|
|
f686d7 |
if (errflag)
|
|
|
f686d7 |
@@ -1329,7 +1329,8 @@ subst_parse_str(char **sp, int single, int err)
|
|
|
f686d7 |
|
|
|
f686d7 |
*sp = s = dupstring(*sp);
|
|
|
f686d7 |
|
|
|
f686d7 |
- if (!(err ? parsestr(s) : parsestrnoerr(s))) {
|
|
|
f686d7 |
+ if (!(err ? parsestr(&s) : parsestrnoerr(&s))) {
|
|
|
f686d7 |
+ *sp = s;
|
|
|
f686d7 |
if (!single) {
|
|
|
f686d7 |
int qt = 0;
|
|
|
f686d7 |
|
|
|
f686d7 |
@@ -1426,7 +1427,8 @@ check_colon_subscript(char *str, char **endp)
|
|
|
f686d7 |
}
|
|
|
f686d7 |
sav = **endp;
|
|
|
f686d7 |
**endp = '\0';
|
|
|
f686d7 |
- if (parsestr(str = dupstring(str)))
|
|
|
f686d7 |
+ str = dupstring(str);
|
|
|
f686d7 |
+ if (parsestr(&str))
|
|
|
f686d7 |
return NULL;
|
|
|
f686d7 |
singsub(&str);
|
|
|
f686d7 |
remnulargs(str);
|
|
|
f686d7 |
diff --git a/Src/utils.c b/Src/utils.c
|
|
|
f686d7 |
index 26e2a5c..2c1d034 100644
|
|
|
f686d7 |
--- a/Src/utils.c
|
|
|
f686d7 |
+++ b/Src/utils.c
|
|
|
f686d7 |
@@ -1440,7 +1440,7 @@ checkmailpath(char **s)
|
|
|
f686d7 |
setunderscore(*s);
|
|
|
f686d7 |
|
|
|
f686d7 |
u = dupstring(u);
|
|
|
f686d7 |
- if (! parsestr(u)) {
|
|
|
f686d7 |
+ if (!parsestr(&u)) {
|
|
|
f686d7 |
singsub(&u);
|
|
|
f686d7 |
zputs(u, shout);
|
|
|
f686d7 |
fputc('\n', shout);
|
|
|
f686d7 |
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
|
|
|
f686d7 |
index bea9459..fa629b2 100644
|
|
|
f686d7 |
--- a/Test/D04parameter.ztst
|
|
|
f686d7 |
+++ b/Test/D04parameter.ztst
|
|
|
f686d7 |
@@ -1551,3 +1551,10 @@
|
|
|
f686d7 |
0:Empty parameter shouldn't cause modifiers to crash the shell
|
|
|
f686d7 |
>
|
|
|
f686d7 |
>
|
|
|
f686d7 |
+
|
|
|
f686d7 |
+# The following tests the return behaviour of parsestr/parsestrnoerr
|
|
|
f686d7 |
+ alias param-test-alias='print $'\''\x45xpanded in substitution'\'
|
|
|
f686d7 |
+ param='$(param-test-alias)'
|
|
|
f686d7 |
+ print ${(e)param}
|
|
|
f686d7 |
+0:Alias expansion in command substitution in parameter evaluation
|
|
|
f686d7 |
+>Expanded in substitution
|
|
|
f686d7 |
--
|
|
|
f686d7 |
2.7.4
|
|
|
f686d7 |
|