From 5a8155f7b7ab8f3cab1f95d4dba5ed49de0ab77c Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Mon, 4 Sep 2017 21:36:46 +0100
Subject: 41633: Fix problem backgrounding function definitions.
Owing to being marked as simple sublists the instruction to
background was ignored. This applied to anonymous functions.
---
Src/parse.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
(limited to 'Src/parse.c')
diff --git a/Src/parse.c b/Src/parse.c
index 27052527d..6e0856bbc 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -808,8 +808,13 @@ par_sublist(int *cmplx)
WC_SUBLIST_END),
f, (e - 1 - p), c);
cmdpop();
- } else
+ } else {
+ if (tok == AMPER || tok == AMPERBANG) {
+ c = 1;
+ *cmplx |= c;
+ }
set_sublist_code(p, WC_SUBLIST_END, f, (e - 1 - p), c);
+ }
return 1;
} else {
ecused--;
--
cgit v1.2.3
From e573857a033504f7918c4a2309151329820f115f Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Wed, 4 Oct 2017 09:18:51 +0100
Subject: 41802 (minor tweaks): use heap during shell function call.
Replaces stack for more efficient memory management.
Also fix debug message when FUNCNEST is increased.
---
ChangeLog | 6 +++
Src/exec.c | 154 +++++++++++++++++++++++++++++++++---------------------------
Src/parse.c | 3 +-
3 files changed, 93 insertions(+), 70 deletions(-)
(limited to 'Src/parse.c')
diff --git a/ChangeLog b/ChangeLog
index f79a204ad..08ccc3470 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2017-10-04 Peter Stephenson
+
+ * 41802 (minor tweaks): Src/exec.c, Src/parse.c: use heap
+ instead of stack for temporary storage over shell function call,
+ also fix debug message when FUNCNEST increased.
+
2017-10-02 Peter Stephenson
* 41787 (minor corrections): configure.ac, README,
diff --git a/Src/exec.c b/Src/exec.c
index dfb50c3b3..fc6d02dc3 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -41,6 +41,20 @@ enum {
ADDVAR_RESTORE = 1 << 2
};
+/* Structure in which to save values around shell function call */
+
+struct funcsave {
+ char opts[OPT_SIZE];
+ char *argv0;
+ int zoptind, lastval, optcind, numpipestats;
+ int *pipestats;
+ char *scriptname;
+ int breaks, contflag, loops, emulation, noerrexit, oflags, restore_sticky;
+ Emulation_options sticky;
+ struct funcstack fstack;
+};
+typedef struct funcsave *Funcsave;
+
/*
* used to suppress ERREXIT and trapping of SIGZERR, SIGEXIT.
* Bits from noerrexit_bits.
@@ -5495,34 +5509,36 @@ int sticky_emulation_differs(Emulation_options sticky2)
mod_export int
doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
{
- char **pptab, **x, *oargv0;
- int oldzoptind, oldlastval, oldoptcind, oldnumpipestats, ret;
- int *oldpipestats = NULL;
- char saveopts[OPT_SIZE], *oldscriptname = scriptname;
+ char **pptab, **x;
+ int ret;
char *name = shfunc->node.nam;
- int flags = shfunc->node.flags, ooflags;
- int savnoerrexit;
+ int flags = shfunc->node.flags;
char *fname = dupstring(name);
- int obreaks, ocontflag, oloops, saveemulation, restore_sticky;
Eprog prog;
- struct funcstack fstack;
static int oflags;
- Emulation_options save_sticky = NULL;
static int funcdepth;
Heap funcheap;
queue_signals(); /* Lots of memory and global state changes coming */
NEWHEAPS(funcheap) {
- oargv0 = NULL;
- obreaks = breaks;
- ocontflag = contflag;
- oloops = loops;
+ /*
+ * Save data in heap rather than on stack to keep recursive
+ * function cost down --- use of heap memory should be efficient
+ * at this point. Saving is not actually massive.
+ */
+ Funcsave funcsave = zhalloc(sizeof(struct funcsave));
+ funcsave->scriptname = scriptname;
+ funcsave->argv0 = NULL;
+ funcsave->breaks = breaks;
+ funcsave->contflag = contflag;
+ funcsave->loops = loops;
+ funcsave->lastval = lastval;
+ funcsave->pipestats = NULL;
+ funcsave->numpipestats = numpipestats;
+ funcsave->noerrexit = noerrexit;
if (trap_state == TRAP_STATE_PRIMED)
trap_return--;
- oldlastval = lastval;
- oldnumpipestats = numpipestats;
- savnoerrexit = noerrexit;
/*
* Suppression of ERR_RETURN is turned off in function scope.
*/
@@ -5533,8 +5549,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
* immediately by a pushheap/popheap pair.
*/
size_t bytes = sizeof(int)*numpipestats;
- oldpipestats = (int *)zhalloc(bytes);
- memcpy(oldpipestats, pipestats, bytes);
+ funcsave->pipestats = (int *)zhalloc(bytes);
+ memcpy(funcsave->pipestats, pipestats, bytes);
}
starttrapscope();
@@ -5543,8 +5559,8 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
pptab = pparams;
if (!(flags & PM_UNDEFINED))
scriptname = dupstring(name);
- oldzoptind = zoptind;
- oldoptcind = optcind;
+ funcsave->zoptind = zoptind;
+ funcsave->optcind = optcind;
if (!isset(POSIXBUILTINS)) {
zoptind = 1;
optcind = 0;
@@ -5553,9 +5569,9 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
/* We need to save the current options even if LOCALOPTIONS is *
* not currently set. That's because if it gets set in the *
* function we need to restore the original options on exit. */
- memcpy(saveopts, opts, sizeof(opts));
- saveemulation = emulation;
- save_sticky = sticky;
+ memcpy(funcsave->opts, opts, sizeof(opts));
+ funcsave->emulation = emulation;
+ funcsave->sticky = sticky;
if (sticky_emulation_differs(shfunc->sticky)) {
/*
@@ -5572,7 +5588,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
*/
sticky = sticky_emulation_dup(shfunc->sticky, 1);
emulation = sticky->emulation;
- restore_sticky = 1;
+ funcsave->restore_sticky = 1;
installemulation(emulation, opts);
if (sticky->n_on_opts) {
OptIndex *onptr;
@@ -5591,7 +5607,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
/* All emulations start with pattern disables clear */
clearpatterndisables();
} else
- restore_sticky = 0;
+ funcsave->restore_sticky = 0;
if (flags & (PM_TAGGED|PM_TAGGED_LOCAL))
opts[XTRACE] = 1;
@@ -5609,11 +5625,11 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
else
opts[WARNNESTEDVAR] = 0;
}
- ooflags = oflags;
+ funcsave->oflags = oflags;
/*
* oflags is static, because we compare it on the next recursive
- * call. Hence also we maintain ooflags for restoring the previous
- * value of oflags after the call.
+ * call. Hence also we maintain a saved version for restoring
+ * the previous value of oflags after the call.
*/
oflags = flags;
opts[PRINTEXITVALUE] = 0;
@@ -5624,7 +5640,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
pparams = x = (char **) zshcalloc(((sizeof *x) *
(1 + countlinknodes(doshargs))));
if (isset(FUNCTIONARGZERO)) {
- oargv0 = argzero;
+ funcsave->argv0 = argzero;
argzero = ztrdup(getdata(node));
}
/* first node contains name regardless of option */
@@ -5634,7 +5650,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
} else {
pparams = (char **) zshcalloc(sizeof *pparams);
if (isset(FUNCTIONARGZERO)) {
- oargv0 = argzero;
+ funcsave->argv0 = argzero;
argzero = ztrdup(argzero);
}
}
@@ -5644,21 +5660,21 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
lastval = 1;
goto undoshfunc;
}
- fstack.name = dupstring(name);
+ funcsave->fstack.name = dupstring(name);
/*
* The caller is whatever is immediately before on the stack,
* unless we're at the top, in which case it's the script
* or interactive shell name.
*/
- fstack.caller = funcstack ? funcstack->name :
- dupstring(oargv0 ? oargv0 : argzero);
- fstack.lineno = lineno;
- fstack.prev = funcstack;
- fstack.tp = FS_FUNC;
- funcstack = &fstack;
+ funcsave->fstack.caller = funcstack ? funcstack->name :
+ dupstring(funcsave->argv0 ? funcsave->argv0 : argzero);
+ funcsave->fstack.lineno = lineno;
+ funcsave->fstack.prev = funcstack;
+ funcsave->fstack.tp = FS_FUNC;
+ funcstack = &funcsave->fstack;
- fstack.flineno = shfunc->lineno;
- fstack.filename = getshfuncfile(shfunc);
+ funcsave->fstack.flineno = shfunc->lineno;
+ funcsave->fstack.filename = getshfuncfile(shfunc);
prog = shfunc->funcdef;
if (prog->flags & EF_RUN) {
@@ -5666,7 +5682,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
prog->flags &= ~EF_RUN;
- runshfunc(prog, NULL, fstack.name);
+ runshfunc(prog, NULL, funcsave->fstack.name);
if (!(shf = (Shfunc) shfunctab->getnode(shfunctab,
(name = fname)))) {
@@ -5679,52 +5695,52 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
}
prog = shf->funcdef;
}
- runshfunc(prog, wrappers, fstack.name);
+ runshfunc(prog, wrappers, funcsave->fstack.name);
doneshfunc:
- funcstack = fstack.prev;
+ funcstack = funcsave->fstack.prev;
undoshfunc:
--funcdepth;
if (retflag) {
retflag = 0;
- breaks = obreaks;
+ breaks = funcsave->breaks;
}
freearray(pparams);
- if (oargv0) {
+ if (funcsave->argv0) {
zsfree(argzero);
- argzero = oargv0;
+ argzero = funcsave->argv0;
}
pparams = pptab;
if (!isset(POSIXBUILTINS)) {
- zoptind = oldzoptind;
- optcind = oldoptcind;
+ zoptind = funcsave->zoptind;
+ optcind = funcsave->optcind;
}
- scriptname = oldscriptname;
- oflags = ooflags;
+ scriptname = funcsave->scriptname;
+ oflags = funcsave->oflags;
endpatternscope(); /* before restoring old LOCALPATTERNS */
- if (restore_sticky) {
+ if (funcsave->restore_sticky) {
/*
* If we switched to an emulation environment just for
* this function, we interpret the option and emulation
* switch as being a firewall between environments.
*/
- memcpy(opts, saveopts, sizeof(opts));
- emulation = saveemulation;
- sticky = save_sticky;
+ memcpy(opts, funcsave->opts, sizeof(opts));
+ emulation = funcsave->emulation;
+ sticky = funcsave->sticky;
} else if (isset(LOCALOPTIONS)) {
/* restore all shell options except PRIVILEGED and RESTRICTED */
- saveopts[PRIVILEGED] = opts[PRIVILEGED];
- saveopts[RESTRICTED] = opts[RESTRICTED];
- memcpy(opts, saveopts, sizeof(opts));
- emulation = saveemulation;
+ funcsave->opts[PRIVILEGED] = opts[PRIVILEGED];
+ funcsave->opts[RESTRICTED] = opts[RESTRICTED];
+ memcpy(opts, funcsave->opts, sizeof(opts));
+ emulation = funcsave->emulation;
} else {
/* just restore a couple. */
- opts[XTRACE] = saveopts[XTRACE];
- opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE];
- opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS];
- opts[LOCALLOOPS] = saveopts[LOCALLOOPS];
- opts[WARNNESTEDVAR] = saveopts[WARNNESTEDVAR];
+ opts[XTRACE] = funcsave->opts[XTRACE];
+ opts[PRINTEXITVALUE] = funcsave->opts[PRINTEXITVALUE];
+ opts[LOCALOPTIONS] = funcsave->opts[LOCALOPTIONS];
+ opts[LOCALLOOPS] = funcsave->opts[LOCALLOOPS];
+ opts[WARNNESTEDVAR] = funcsave->opts[WARNNESTEDVAR];
}
if (opts[LOCALLOOPS]) {
@@ -5732,9 +5748,9 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
zwarn("`continue' active at end of function scope");
if (breaks)
zwarn("`break' active at end of function scope");
- breaks = obreaks;
- contflag = ocontflag;
- loops = oloops;
+ breaks = funcsave->breaks;
+ contflag = funcsave->contflag;
+ loops = funcsave->loops;
}
endtrapscope();
@@ -5742,11 +5758,11 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
if (trap_state == TRAP_STATE_PRIMED)
trap_return++;
ret = lastval;
- noerrexit = savnoerrexit;
+ noerrexit = funcsave->noerrexit;
if (noreturnval) {
- lastval = oldlastval;
- numpipestats = oldnumpipestats;
- memcpy(pipestats, oldpipestats, sizeof(int)*numpipestats);
+ lastval = funcsave->lastval;
+ numpipestats = funcsave->numpipestats;
+ memcpy(pipestats, funcsave->pipestats, sizeof(int)*numpipestats);
}
} OLDHEAPS;
diff --git a/Src/parse.c b/Src/parse.c
index 6e0856bbc..5fe3ebd2c 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -2742,7 +2742,8 @@ freeeprog(Eprog p)
DPUTS(p->nref < 0 && !(p->flags & EF_HEAP), "Real EPROG has nref < 0");
DPUTS(p->nref < -1, "Uninitialised EPROG nref");
#ifdef MAX_FUNCTION_DEPTH
- DPUTS(p->nref > MAX_FUNCTION_DEPTH + 10, "Overlarge EPROG nref");
+ DPUTS(zsh_funcnest >=0 && p->nref > zsh_funcnest + 10,
+ "Overlarge EPROG nref");
#endif
if (p->nref > 0 && !--p->nref) {
for (i = p->npats, pp = p->pats; i--; pp++)
--
cgit v1.2.3
From 97c74dcb0e5a22d57759c15d64eaeab87ba410f1 Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Tue, 12 Dec 2017 09:13:41 +0000
Subject: 42110: Fix redirections between variable assignments at start of line
---
ChangeLog | 5 +++++
Src/parse.c | 4 ++++
Test/A04redirect.ztst | 7 +++++++
3 files changed, 16 insertions(+)
(limited to 'Src/parse.c')
diff --git a/ChangeLog b/ChangeLog
index b99d5e11e..16fcd3f61 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2017-12-12 Peter Stephenson
+
+ * 42110: Src/parse.c, Test/A04redirect.ztst: fix redirection in
+ between variable assignments at start of line.
+
2017-12-01 Peter Stephenson
* dana: 42065: Test/B10getopts.ztst: new getopts tests.
diff --git a/Src/parse.c b/Src/parse.c
index 5fe3ebd2c..6af2550df 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -1848,6 +1848,10 @@ par_simple(int *cmplx, int nr)
incmdpos = oldcmdpos;
isnull = 0;
assignments = 1;
+ } else if (IS_REDIROP(tok)) {
+ *cmplx = c = 1;
+ nr += par_redir(&r, NULL);
+ continue;
} else
break;
zshlex();
diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst
index cb82751ce..b8105cf6d 100644
--- a/Test/A04redirect.ztst
+++ b/Test/A04redirect.ztst
@@ -622,3 +622,10 @@
>FOO
>HERE
>}
+
+ a=b 2>/dev/null c=d
+ print $a
+ print $c
+0:Redirect in the middle of assignments
+>b
+>d
--
cgit v1.2.3
From 54ea6a8cd54c518e11a23275501f92806182f997 Mon Sep 17 00:00:00 2001
From: Martijn Dekker
Date: Wed, 14 Feb 2018 07:11:14 +0100
Subject: 42365: Use .zwc file if timestamp identical to source.
This can happen if the files are bundled together.
---
ChangeLog | 5 +++++
Src/parse.c | 8 ++++----
2 files changed, 9 insertions(+), 4 deletions(-)
(limited to 'Src/parse.c')
diff --git a/ChangeLog b/ChangeLog
index 463510d08..ba42b72e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2018-03-05 Peter Stephenson
+
+ * Martijn: 42365: Src/parse.c: use .zwc file if timestamp
+ identical to source file.
+
2018-03-04 Peter Stephenson
* Taylor West: 42411: Src/mem.c: assume any current C compiler
diff --git a/Src/parse.c b/Src/parse.c
index 6af2550df..47e5a246a 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -3677,15 +3677,15 @@ try_dump_file(char *path, char *name, char *file, int *ksh, int test_only)
* function. */
queue_signals();
if (!rd &&
- (rc || std.st_mtime > stc.st_mtime) &&
- (rn || std.st_mtime > stn.st_mtime) &&
+ (rc || std.st_mtime >= stc.st_mtime) &&
+ (rn || std.st_mtime >= stn.st_mtime) &&
(prog = check_dump_file(dig, &std, name, ksh, test_only))) {
unqueue_signals();
return prog;
}
/* No digest file. Now look for the per-function compiled file. */
if (!rc &&
- (rn || stc.st_mtime > stn.st_mtime) &&
+ (rn || stc.st_mtime >= stn.st_mtime) &&
(prog = check_dump_file(wc, &stc, name, ksh, test_only))) {
unqueue_signals();
return prog;
@@ -3724,7 +3724,7 @@ try_source_file(char *file)
rn = stat(file, &stn);
queue_signals();
- if (!rc && (rn || stc.st_mtime > stn.st_mtime) &&
+ if (!rc && (rn || stc.st_mtime >= stn.st_mtime) &&
(prog = check_dump_file(wc, &stc, tail, NULL, 0))) {
unqueue_signals();
return prog;
--
cgit v1.2.3