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