summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog42
-rw-r--r--Completion/Unix/Command/_surfraw74
-rw-r--r--Completion/X/Command/_gv5
-rw-r--r--Doc/Zsh/options.yo16
-rw-r--r--Misc/vcs_info-examples8
-rw-r--r--README10
-rw-r--r--Src/exec.c10
-rw-r--r--Src/hist.c20
-rw-r--r--Src/input.c4
-rw-r--r--Src/mem.c43
-rw-r--r--Src/options.c1
-rw-r--r--Src/pattern.c9
-rw-r--r--Src/watch.c4
-rw-r--r--Src/zsh.h1
-rw-r--r--Test/B07emulate.ztst22
15 files changed, 182 insertions, 87 deletions
diff --git a/ChangeLog b/ChangeLog
index a21b405c8..a35eb6501 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,47 @@
+2021-04-13 dana <dana@dana.is>
+
+ * Daniel Shahaf: 48522: README: Clarify _alternative change
+
+2021-04-13 Tim Lee <progscriptclone@gmail.com>
+
+ * 48525: Misc/vcs_info-examples: vcs_info git docs: ahead/behind
+ commits: Run fewer external programs
+
+2021-04-12 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 48439: Src/mem.c: remove macros that became unnecessary by 47785
+
+2021-04-11 Oliver Kiddle <opk@zsh.org>
+
+ * 48504: Src/hist.c, Src/input.c, Src/watch.c:
+ use SEEK_ macros in fseek() calls
+
+ * Michael Stapelberg: 45396: Src/hist.c: readhistfile:
+ avoid thousands of lseek(2) syscalls via ftell()
+
+ * Marc Chantreux: 48466: Completion/Unix/Command/_surfraw:
+ correct indentation and remove tabs and trailing spaces
+
+ * Marc Chantreux: 48445: Completion/Unix/Command/_surfraw:
+ pluralize tags in _surfraw
+
+ * Marc Chantreux: users/26645: Completion/X/Command/_gv:
+ update options in gv completion
+
+2021-04-10 Bart Schaefer <schaefer@zsh.org>
+
+ * 47913: Doc/Zsh/options.yo, Src/options.c, Src/pattern.c, Src/zsh.h:
+ implement CASE_PATHS option to make NO_CASE_GLOB more sensible
+
2021-04-10 dana <dana@dana.is>
+ * brian m. carlson: 47794: README, Src/exec.c,
+ Test/B07emulate.ztst: exec: run final pipeline command in a
+ subshell in sh mode
+
+ * unposted (see 48415): README: Document incompatibility
+ caused by workers/43928
+
* 48338: Completion/Unix/Command/_git: Support case-insensitive
path matching
diff --git a/Completion/Unix/Command/_surfraw b/Completion/Unix/Command/_surfraw
index 4838f1e58..d153cd493 100644
--- a/Completion/Unix/Command/_surfraw
+++ b/Completion/Unix/Command/_surfraw
@@ -20,11 +20,11 @@ case $state in
subcmd)
args=(
'-help[display help information]'
- '*:string:_guard "^-*" "search string"'
+ '*: :_guard "^-*" "search string"'
)
case "$words[1]" in
ask|cia|cnn|deblogs|excite|filesearching|foldoc|happypenguin|slashdot|slinuxdoc|sundocs|sunsolve|xxx)
- _message -e string 'search string'
+ _message -e strings 'search string'
;;
alioth)
_arguments $args \
@@ -64,10 +64,10 @@ case $state in
'*:search string' && ret=0
;;
ctan)
- _arguments $args \
- '-name[search by filename]' \
- '-desc[search descriptions (default)]'\
- '-doc[search documentation]'
+ _arguments $args \
+ '-name[search by filename]' \
+ '-desc[search descriptions (default)]'\
+ '-doc[search documentation]'
;;
currency)
_arguments \
@@ -164,8 +164,8 @@ case $state in
'-doc[view PTS documentation]' && ret=0
;;
debsec)
- _message -e string 'package name, bug number or CVE ID'
- ;;
+ _message -e strings 'package name, bug number or CVE ID'
+ ;;
deja)
_arguments $args \
'-results=-:[number of results to return]' \
@@ -183,7 +183,7 @@ case $state in
;;
ebay)
_arguments $args \
- '-country=-:country:(com de uk fr)' \
+ '-country=-:country:(com de uk fr)' \
'-results=-:[number of results to return]:number' && ret=0
;;
etym)
@@ -220,7 +220,7 @@ case $state in
_deb_packages avail && ret=0
;;
fsfdir)
- _arguments $args
+ _arguments $args
;;
google)
_arguments $args \
@@ -229,19 +229,19 @@ case $state in
'-search=-:topic:(bsd linux mac unclesam)' && ret=0
;;
gutenberg)
- _arguments $args \
- '-title[search titles (default)]'
- '-author[search authors]'
- '-num[search etext numbers]'
- ;;
+ _arguments $args \
+ '-title[search titles (default)]'
+ '-author[search authors]'
+ '-num[search etext numbers]'
+ ;;
imdb)
_arguments $args \
'-category=-:category:(All Titles MyMovies People Characters Quotes Bios Plots)' && ret=0
;;
ixquick)
- _arguments $args \
- '-search=-:search type:(web pics)' \
- '-lang=-:language:(english dansk deutsch espanol francais italiano nederlands norsk polski portugues suomi svenska turkce jiantizhongwen nihongo fantizhengwen hangul)'
+ _arguments $args \
+ '-search=-:search type:(web pics)' \
+ '-lang=-:language:(english dansk deutsch espanol francais italiano nederlands norsk polski portugues suomi svenska turkce jiantizhongwen nihongo fantizhengwen hangul)'
;;
jake)
_arguments $args \
@@ -261,9 +261,9 @@ case $state in
'-head=:display headlines:(on off)' \
'-grid=:show results in grid:(on off)' \
'-spell=:spelling tolerance:(off standard force)' \
- '*:dictionary word:->dictword' && ret=0
+ '*:dictionary word:->words' && ret=0
- [[ "$state" = dictword ]] && _wanted words expl 'dictionary word' \
+ [[ "$state" = words ]] && _wanted words expl 'dictionary word' \
compadd $(look "${PREFIX}") && ret=0
;;
netbsd|openbsd)
@@ -386,20 +386,20 @@ case $state in
:URL:_urls && ret=0
;;
wayback)
- _arguments $args \
- '-syear=-[start search from this year]:year' \
- '-smonth=-:[start search from this month]:month:(jan feb mar apr may jun jul aug sep oct nov dec)' \
- '-sday=-[start search from this day]:number' \
- '-eyear=-[end search in this year]:year' \
- '-emonth=-[end search in this month]:month:(jan feb mar apr may jun jul aug sep oct nov dec)' \
- '-eday=-[end search in this day]:number' \
- '-list[list all pages that match search criteria]' \
- '-dups[show dups]' \
- '-compare[compare pages]' \
- '-pdf[show as PDF]' \
- '-alias=-[how to handle site aliases]:alias:(merge show hide)' \
- '-redir=-[how to handle redirections]:redir:(hide flag show)' \
- '-type=-[file type to search for]:type:(image audio video binary text pdf)'
+ _arguments $args \
+ '-syear=-[start search from this year]:year' \
+ '-smonth=-:[start search from this month]:month:(jan feb mar apr may jun jul aug sep oct nov dec)' \
+ '-sday=-[start search from this day]:number' \
+ '-eyear=-[end search in this year]:year' \
+ '-emonth=-[end search in this month]:month:(jan feb mar apr may jun jul aug sep oct nov dec)' \
+ '-eday=-[end search in this day]:number' \
+ '-list[list all pages that match search criteria]' \
+ '-dups[show dups]' \
+ '-compare[compare pages]' \
+ '-pdf[show as PDF]' \
+ '-alias=-[how to handle site aliases]:alias:(merge show hide)' \
+ '-redir=-[how to handle redirections]:redir:(hide flag show)' \
+ '-type=-[file type to search for]:type:(image audio video binary text pdf)'
;;
wetandwild)
_arguments \
@@ -422,10 +422,10 @@ case $state in
'-results=-[specify number of results to return]:number' && ret=0
;;
yubnub)
- _message -e command 'Yubnub Command'
+ _message -e commands 'Yubnub Command'
;;
*)
- _message -e string 'search string'
+ _message -e strings 'search string'
;;
esac
;;
@@ -434,7 +434,7 @@ case $state in
local it
# list the applets
set -- ${${(f)"$(_call_program elvi surfraw -elvi)"}%%[[:space:]]##-- *}
- shift # the first line is an header: remove it
+ shift # the first line is a header: remove it
# then list the bookmarks
for it in \
$^xdg_config_dirs/surfraw/bookmarks(Nr) \
diff --git a/Completion/X/Command/_gv b/Completion/X/Command/_gv
index cde8a1c1a..9b11ad31c 100644
--- a/Completion/X/Command/_gv
+++ b/Completion/X/Command/_gv
@@ -28,8 +28,11 @@ _arguments \
'(--portrait --seascape --upsidedown)--landscape' \
'(--portrait --landscape --upsidedown)--seascape' \
'(--portrait --landscape --seascape)--upsidedown' \
- --{help,spartan} \
-{h,v} \
+ -{,-}{help,version} \
+ -{,-}{spartan,widgetless,presentation,fullscreen} \
+ -{,-}{infoSilent,infoErrors,infoAll} \
+ -{,-}'password=:password:' \
'--arguments=:ghostscript arguments:' \
'--page=:label of first page:' \
'--media=:page size:(Letter Legal Statement Tabloid Ledger Folio Quarto 10x14 Executive A3 A4 A5 B4 B5)' \
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index 6a1f82b07..6e862fae8 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -474,6 +474,22 @@ item(tt(CASE_MATCH) <D>)(
Make regular expressions using the tt(zsh/regex) module (including
matches with tt(=~)) sensitive to case.
)
+pindex(CASE_PATHS)
+pindex(NO_CASE_PATHS)
+pindex(CASEPATHS)
+pindex(NOCASEPATHS)
+cindex(case-sensitive globbing, option)
+item(tt(CASE_PATHS))(
+If tt(CASE_PATHS) is not set (the default), tt(CASE_GLOB) affects the
+interpretation of em(every) path component, whenever a special
+character appears in em(any) component. When tt(CASE_PATHS) is set,
+file path components that do em(not) contain special filename
+generation characters are always sensitive to case, thus restricting
+tt(NO_CASE_GLOB) to components that contain globbing characters.
+
+Note that if the filesystem itself is not sensitive to case, then
+tt(CASE_PATHS) has no effect.
+)
pindex(CSH_NULL_GLOB)
pindex(NO_CSH_NULL_GLOB)
pindex(CSHNULLGLOB)
diff --git a/Misc/vcs_info-examples b/Misc/vcs_info-examples
index 94b8a7b5e..d33d0ceed 100644
--- a/Misc/vcs_info-examples
+++ b/Misc/vcs_info-examples
@@ -179,14 +179,10 @@ function +vi-git-st() {
local ahead behind
local -a gitstatus
- # for git prior to 1.7
- # ahead=$(git rev-list origin/${hook_com[branch]}..HEAD | wc -l)
- ahead=$(git rev-list ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null | wc -l)
+ ahead=$(git rev-list --count ${hook_com[branch]}@{upstream}..HEAD 2>/dev/null)
(( $ahead )) && gitstatus+=( "+${ahead}" )
- # for git prior to 1.7
- # behind=$(git rev-list HEAD..origin/${hook_com[branch]} | wc -l)
- behind=$(git rev-list HEAD..${hook_com[branch]}@{upstream} 2>/dev/null | wc -l)
+ behind=$(git rev-list --count HEAD..${hook_com[branch]}@{upstream} 2>/dev/null)
(( $behind )) && gitstatus+=( "-${behind}" )
hook_com[misc]+=${(j:/:)gitstatus}
diff --git a/README b/README
index 1eb38a608..76bf4ec35 100644
--- a/README
+++ b/README
@@ -95,6 +95,10 @@ right thing, but this should be viewed as an unsupported hack.)
The XTRACE option is now disabled while running user-defined completion
widgets. See NEWS.
+emulate sh: When zsh emulates sh, the final command in a pipeline is now run in
+a subshell. This differs from the behavior in the native (zsh) mode, but is
+consistent with most other sh implementations.
+
Incompatibilities between 5.7.1 and 5.8
---------------------------------------
@@ -144,6 +148,12 @@ reverse order, from last applied to first applied.
variables without a preceding '$' sign in shell arithmetic expansion
and in the double-parentheses and 'let' arithmetic commands.
+3) _alternative now correctly handles the same (...) action syntax as
+_arguments; this may necessitate quoting/escaping in calls to _alternative
+and _regex_arguments that wasn't previously required. See
+https://zsh.org/workers/48414 (commit zsh-5.8-348-g2c000ee7b) for details
+and an example.
+
Incompatibilities between 5.5.1 and 5.6.2
------------------------------------------
diff --git a/Src/exec.c b/Src/exec.c
index 2301f85ad..6f09e0d9f 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -2901,11 +2901,13 @@ execcmd_exec(Estate state, Execcmd_params eparams,
pushnode(args, dupstring("fg"));
}
- if ((how & Z_ASYNC) || output) {
+ if ((how & Z_ASYNC) || output ||
+ (last1 == 2 && input && EMULATION(EMULATE_SH))) {
/*
- * If running in the background, or not the last command in a
- * pipeline, we don't need any of the rest of this function to
- * affect the state in the main shell, so fork immediately.
+ * If running in the background, not the last command in a
+ * pipeline, or the last command in a multi-stage pipeline
+ * in sh mode, we don't need any of the rest of this function
+ * to affect the state in the main shell, so fork immediately.
*
* In other cases we may need to process the command line
* a bit further before we make the decision.
diff --git a/Src/hist.c b/Src/hist.c
index 8ab7828e8..42cae030c 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -2589,11 +2589,13 @@ resizehistents(void)
}
static int
-readhistline(int start, char **bufp, int *bufsiz, FILE *in)
+readhistline(int start, char **bufp, int *bufsiz, FILE *in, int *readbytes)
{
char *buf = *bufp;
if (fgets(buf + start, *bufsiz - start, in)) {
- int len = start + strlen(buf + start);
+ int len = strlen(buf + start);
+ *readbytes += len;
+ len += start;
if (len == start)
return -1;
if (buf[len - 1] != '\n') {
@@ -2602,7 +2604,7 @@ readhistline(int start, char **bufp, int *bufsiz, FILE *in)
return -1;
*bufp = zrealloc(buf, 2 * (*bufsiz));
*bufsiz = 2 * (*bufsiz);
- return readhistline(len, bufp, bufsiz, in);
+ return readhistline(len, bufp, bufsiz, in, readbytes);
}
}
else {
@@ -2610,7 +2612,7 @@ readhistline(int start, char **bufp, int *bufsiz, FILE *in)
if (len > 1 && buf[len - 2] == '\\') {
buf[--len - 1] = '\n';
if (!feof(in))
- return readhistline(len, bufp, bufsiz, in);
+ return readhistline(len, bufp, bufsiz, in, readbytes);
}
}
return len;
@@ -2630,7 +2632,7 @@ readhistfile(char *fn, int err, int readflags)
short *words;
struct stat sb;
int nwordpos, nwords, bufsiz;
- int searching, newflags, l, ret, uselex;
+ int searching, newflags, l, ret, uselex, readbytes;
if (!fn && !(fn = getsparam("HISTFILE")))
return;
@@ -2662,7 +2664,7 @@ readhistfile(char *fn, int err, int readflags)
pushheap();
if (readflags & HFILE_FAST && lasthist.text) {
if (lasthist.fpos < lasthist.fsiz) {
- fseek(in, lasthist.fpos, 0);
+ fseek(in, lasthist.fpos, SEEK_SET);
searching = 1;
}
else {
@@ -2672,13 +2674,15 @@ readhistfile(char *fn, int err, int readflags)
} else
searching = 0;
+ fpos = ftell(in);
+ readbytes = 0;
newflags = HIST_OLD | HIST_READ;
if (readflags & HFILE_FAST)
newflags |= HIST_FOREIGN;
if (readflags & HFILE_SKIPOLD
|| (hist_ignore_all_dups && newflags & hist_skip_flags))
newflags |= HIST_MAKEUNIQUE;
- while (fpos = ftell(in), (l = readhistline(0, &buf, &bufsiz, in))) {
+ while (fpos += readbytes, readbytes = 0, (l = readhistline(0, &buf, &bufsiz, in, &readbytes))) {
char *pt;
int remeta = 0;
@@ -2737,7 +2741,7 @@ readhistfile(char *fn, int err, int readflags)
&& histstrcmp(pt, lasthist.text) == 0)
searching = 0;
else {
- fseek(in, 0, 0);
+ fseek(in, 0, SEEK_SET);
histfile_linect = 0;
searching = -1;
}
diff --git a/Src/input.c b/Src/input.c
index e9989ffe4..f568cc135 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -495,9 +495,9 @@ stuff(char *fn)
zerr("can't open %s", fn);
return 1;
}
- fseek(in, 0, 2);
+ fseek(in, 0, SEEK_END);
len = ftell(in);
- fseek(in, 0, 0);
+ fseek(in, 0, SEEK_SET);
buf = (char *)zalloc(len + 1);
if (!(fread(buf, len, 1, in))) {
zerr("read error on %s", fn);
diff --git a/Src/mem.c b/Src/mem.c
index 25b2bbce7..fb4be47bf 100644
--- a/Src/mem.c
+++ b/Src/mem.c
@@ -1072,11 +1072,6 @@ zrealloc(void *ptr, size_t size)
# endif
#endif
-#define FREE_RET_T void
-#define FREE_ARG_T void *
-#define MALLOC_RET_T void *
-#define MALLOC_ARG_T size_t
-
/* structure for building free list in blocks holding small blocks */
struct m_shdr {
@@ -1190,8 +1185,8 @@ static struct m_hdr *m_l;
#endif /* ZSH_MEM_DEBUG */
-MALLOC_RET_T
-malloc(MALLOC_ARG_T size)
+void *
+malloc(size_t size)
{
struct m_hdr *m, *mp, *mt;
long n, s, os = 0;
@@ -1218,7 +1213,7 @@ malloc(MALLOC_ARG_T size)
#if 1
size = 1;
#else
- return (MALLOC_RET_T) m_high;
+ return (void *) m_high;
#endif
queue_signals(); /* just queue signals rather than handling them */
@@ -1276,7 +1271,7 @@ malloc(MALLOC_ARG_T size)
#endif
unqueue_signals();
- return (MALLOC_RET_T) sh;
+ return (void *) sh;
}
/* we still want a small block but there were no block with a free
small block of the requested size; so we use the real allocation
@@ -1418,14 +1413,14 @@ malloc(MALLOC_ARG_T size)
#endif
unqueue_signals();
- return (MALLOC_RET_T) (((char *)m) + sizeof(struct m_hdr));
+ return (void *) (((char *)m) + sizeof(struct m_hdr));
}
#ifdef ZSH_MEM_DEBUG
m_m[m->len < (1024 * M_ISIZE) ? (m->len / M_ISIZE) : 1024]++;
#endif
unqueue_signals();
- return (MALLOC_RET_T) & m->next;
+ return (void *) & m->next;
}
/* this is an internal free(); the second argument may, but need not hold
@@ -1632,14 +1627,10 @@ zfree(void *p, int sz)
unqueue_signals();
}
-FREE_RET_T
-free(FREE_ARG_T p)
+void
+free(void *p)
{
zfree(p, 0); /* 0 means: size is unknown */
-
-#ifdef FREE_DO_RET
- return 0;
-#endif
}
/* this one is for strings (and only strings, real strings, real C strings,
@@ -1653,8 +1644,8 @@ zsfree(char *p)
zfree(p, strlen(p) + 1);
}
-MALLOC_RET_T
-realloc(MALLOC_RET_T p, MALLOC_ARG_T size)
+void *
+realloc(void *p, size_t size)
{
struct m_hdr *m = (struct m_hdr *)(((char *)p) - M_ISIZE), *mt;
char *r;
@@ -1665,12 +1656,12 @@ realloc(MALLOC_RET_T p, MALLOC_ARG_T size)
queue_signals();
r = malloc(size);
unqueue_signals();
- return (MALLOC_RET_T) r;
+ return (void *) r;
}
/* and some systems even do this... */
if (!p || !size)
- return (MALLOC_RET_T) p;
+ return p;
queue_signals(); /* just queue signals caught rather than handling them */
@@ -1699,17 +1690,17 @@ realloc(MALLOC_RET_T p, MALLOC_ARG_T size)
free(p);
unqueue_signals();
- return (MALLOC_RET_T) r;
+ return (void *) r;
}
-MALLOC_RET_T
-calloc(MALLOC_ARG_T n, MALLOC_ARG_T size)
+void *
+calloc(size_t n, size_t size)
{
long l;
char *r;
if (!(l = n * size))
- return (MALLOC_RET_T) m_high;
+ return (void *) m_high;
/*
* use realloc() (with a NULL `p` argument it behaves exactly the same
@@ -1721,7 +1712,7 @@ calloc(MALLOC_ARG_T n, MALLOC_ARG_T size)
memset(r, 0, l);
- return (MALLOC_RET_T) r;
+ return (void *) r;
}
#ifdef ZSH_MEM_DEBUG
diff --git a/Src/options.c b/Src/options.c
index 23935ae18..783022591 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -105,6 +105,7 @@ static struct optname optns[] = {
{{NULL, "bsdecho", OPT_EMULATE|OPT_SH}, BSDECHO},
{{NULL, "caseglob", OPT_ALL}, CASEGLOB},
{{NULL, "casematch", OPT_ALL}, CASEMATCH},
+{{NULL, "casepaths", 0}, CASEPATHS},
{{NULL, "cbases", 0}, CBASES},
{{NULL, "cprecedences", OPT_EMULATE|OPT_NONZSH}, CPRECEDENCES},
{{NULL, "cdablevars", OPT_EMULATE}, CDABLEVARS},
diff --git a/Src/pattern.c b/Src/pattern.c
index c28f2c9fb..c0e31b78e 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -509,7 +509,7 @@ void
patcompstart(void)
{
patcompcharsset();
- if (isset(CASEGLOB))
+ if (isset(CASEGLOB) || isset(CASEPATHS))
patglobflags = 0;
else
patglobflags = GF_IGNCASE;
@@ -632,6 +632,13 @@ patcompile(char *exp, int inflags, char **endexp)
p->patmlen = len;
p->patnpar = patnpar-1;
+#ifndef __CYGWIN__ /* The filesystem itself is case-insensitive on Cygwin */
+ if ((patflags & PAT_FILE) && !isset(CASEGLOB) && !(patflags & PAT_PURES)) {
+ p->globflags |= GF_IGNCASE;
+ p->globend |= GF_IGNCASE;
+ }
+#endif
+
if (!strp) {
pscan = (Upat)(patout + startoff);
diff --git a/Src/watch.c b/Src/watch.c
index 93b3cb134..c41704315 100644
--- a/Src/watch.c
+++ b/Src/watch.c
@@ -169,9 +169,9 @@ getlogtime(WATCH_STRUCT_UTMP *u, int inout)
return u->ut_time;
if (!(in = fopen(WATCH_WTMP_FILE, "r")))
return time(NULL);
- fseek(in, 0, 2);
+ fseek(in, 0, SEEK_END);
do {
- if (fseek(in, ((first) ? -1 : -2) * sizeof(WATCH_STRUCT_UTMP), 1)) {
+ if (fseek(in, ((first) ? -1 : -2) * sizeof(WATCH_STRUCT_UTMP), SEEK_CUR)) {
fclose(in);
return time(NULL);
}
diff --git a/Src/zsh.h b/Src/zsh.h
index 490407ad0..af9b4fb67 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2389,6 +2389,7 @@ enum {
BSDECHO,
CASEGLOB,
CASEMATCH,
+ CASEPATHS,
CBASES,
CDABLEVARS,
CDSILENT,
diff --git a/Test/B07emulate.ztst b/Test/B07emulate.ztst
index 7b1592fa9..45c39b51d 100644
--- a/Test/B07emulate.ztst
+++ b/Test/B07emulate.ztst
@@ -276,3 +276,25 @@ F:Some reserved tokens are handled in alias expansion
0:--emulate followed by other options
>yes
>no
+
+ emulate sh -c '
+ foo () {
+ VAR=foo &&
+ echo $VAR | bar &&
+ echo "$VAR"
+ }
+ bar () {
+ tr f b &&
+ VAR="$(echo bar | tr r z)" &&
+ echo "$VAR"
+ }
+ foo
+ '
+ emulate sh -c 'func() { echo | local def="abc"; echo $def;}; func'
+ emulate sh -c 'abc="def"; echo | abc="ghi"; echo $abc'
+0:emulate sh uses subshell for last pipe entry
+>boo
+>baz
+>foo
+>
+>def