From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_NONE,RDNS_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 Received: (qmail 1011 invoked from network); 20 Mar 2020 02:15:41 -0000 Received-SPF: pass (primenet.com.au: domain of zsh.org designates 203.24.36.2 as permitted sender) receiver=inbox.vuxu.org; client-ip=203.24.36.2 envelope-from= Received: from unknown (HELO primenet.com.au) (203.24.36.2) by inbox.vuxu.org with ESMTP; 20 Mar 2020 02:15:41 -0000 Received: (qmail 14245 invoked by alias); 20 Mar 2020 02:04:55 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: List-Unsubscribe: X-Seq: 45583 Received: (qmail 299 invoked by uid 1010); 20 Mar 2020 02:04:55 -0000 X-Qmail-Scanner-Diagnostics: from wout3-smtp.messagingengine.com by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.102.2/25751. spamassassin: 3.4.2. Clear:RC:0(64.147.123.19):SA:0(-2.6/5.0):. Processed in 6.749349 secs); 20 Mar 2020 02:04:55 -0000 X-Envelope-From: d.s@daniel.shahaf.name X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: none (ns1.primenet.com.au: domain at daniel.shahaf.name does not designate permitted sender hosts) X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedugedrudegtddggeefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucenucfjughrpeffhffvuffkjghfofggtgesmhdttd erredtjeenucfhrhhomhepffgrnhhivghlucfuhhgrhhgrfhcuoegurdhssegurghnihgv lhdrshhhrghhrghfrdhnrghmvgeqnecukfhppeejledrudekvddrudeftddrudefheenuc evlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegurdhssegu rghnihgvlhdrshhhrghhrghfrdhnrghmvg X-ME-Proxy: Date: Fri, 20 Mar 2020 02:04:06 +0000 From: Daniel Shahaf To: zsh-workers@zsh.org Subject: Re: RFC: function -T f { =?UTF-8?B?4oCm?= } Message-ID: <20200320020406.1a2d34e2@tarpaulin.shahaf.local2> In-Reply-To: References: <20200318183026.35e74654@tarpaulin.shahaf.local2> X-Mailer: Claws Mail 3.17.3 (GTK+ 2.24.32; x86_64-pc-linux-gnu) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="MP_/tI.aMlK5M8vxSBnoqCbKuhK" --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Peter Stephenson wrote on Wed, 18 Mar 2020 19:53 +0000: > On Wed, 2020-03-18 at 18:30 +0000, Daniel Shahaf wrote: > > How about adding a =C2=ABfunction -T f { =E2=80=A6 }=C2=BB syntax, that= defines a > > function and enables tracing for it simultaneously? > >=20 > > I've often found myself going to the first line of a function, copying > > its name, then going to the closing brace of the function and adding > > a =C2=ABfunctions -T $thefunctionsname=C2=BB statement there, in order = to have > > tracing enabled during multiple =C2=ABzsh -f=C2=BB runs. > >=20 > > It's backwards incompatible, but not more than =C2=ABprintf -v=C2=BB wa= s. =20 >=20 > Can't see any objection, and can't see an easy workaround. Thanks for the sanity check, Peter. Patch series attached. The first six patches are no-ops; the functional change is confined to the last three patches. Furthermore, patch #9 changes some of the lines added by patch #8, so y'all may find it easier to review the cumulative diff of those two patches=C2=B9 than to review them one by one. Regarding the man page patch, I wanted to have have the documentation of =C2=ABfunction=C2=BB hyperlink directly to the documentation of =C2=ABty= peset=C2=BB (in the HTML/PDF output formats), but didn't figure out how to do this. > It does work for autoloads --- you can turn on xtrace before the > function is loaded. *nod* =C2=ABautoload -T foo=C2=BB and =C2=ABautoload foo; functions -T foo= =C2=BB both work; however, in my use-cases I'm normally trying to trace a function that's defined in the middle of a *.zsh file that also defines multiple other functions. Cheers, Daniel =C2=B9 For example, using =C2=ABcombinediff <8-9>*=C2=BB or =C2=ABgit diff = HEAD^^=C2=BB. --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0001-internal-Remove-a-redundant-assignment.patch.txt >From 4a8d83f9b86f0ad6041640e9ad28781ad440036e Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 18 Mar 2020 19:42:08 +0000 Subject: [PATCH 1/9] internal: Remove a redundant assignment. The value is overwritten five lines below, without being read in the interim. --- Src/exec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Src/exec.c b/Src/exec.c index bca051d4f..cd014ff38 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -5166,7 +5166,6 @@ execfuncdef(Estate state, Eprog redir_prog) end = beg + WC_FUNCDEF_SKIP(state->pc[-1]); names = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok); - nprg = end - beg; sbeg = *state->pc++; nstrs = *state->pc++; npats = *state->pc++; --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0002-internal-Reduce-some-variables-visibility.-No-fu.patch.txt >From e4ad3e10812fd54a46a91f08b7943ea18b813a55 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 18 Mar 2020 17:45:23 +0000 Subject: [PATCH 2/9] internal: Reduce some variables' visibility. No functional change. --- Src/parse.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Src/parse.c b/Src/parse.c index de1b27967..bd974a573 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -253,14 +253,13 @@ struct heredocs *hdocs; * to avoid a lot of string parsing and some more string duplication. */ -/**/ -int eclen, ecused, ecnpats; -/**/ -Wordcode ecbuf; -/**/ -Eccstr ecstrs; -/**/ -int ecsoffs, ecssub, ecnfunc; +static int eclen, ecused, ecnpats; + +static Wordcode ecbuf; + +static Eccstr ecstrs; + +static int ecsoffs, ecssub, ecnfunc; #define EC_INIT_SIZE 256 #define EC_DOUBLE_THRESHOLD 32768 --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0003-internal-Add-some-comments-around-Eccstr.-No-fun.patch.txt >From cce0d2cfe2d4728d4dcbc2a56cb8243ecd58a80e Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 21:14:42 +0000 Subject: [PATCH 3/9] internal: Add some comments around Eccstr. No functional change. --- Src/parse.c | 31 +++++++++++++++++++++++++++---- Src/zsh.h | 24 ++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 6 deletions(-) diff --git a/Src/parse.c b/Src/parse.c index bd974a573..39d2172d4 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -253,13 +253,24 @@ struct heredocs *hdocs; * to avoid a lot of string parsing and some more string duplication. */ -static int eclen, ecused, ecnpats; +/* Number of wordcodes allocated. */ +static int eclen; +/* Number of wordcodes populated. */ +static int ecused; +/* Number of patterns... */ +static int ecnpats; static Wordcode ecbuf; static Eccstr ecstrs; -static int ecsoffs, ecssub, ecnfunc; +static int ecsoffs, ecssub; + +/* + * ### The number of starts and ends of function definitions up to this point. + * Never decremented. + */ +static int ecnfunc; #define EC_INIT_SIZE 256 #define EC_DOUBLE_THRESHOLD 32768 @@ -363,7 +374,11 @@ ecispace(int p, int n) ecadjusthere(p, n); } -/* Add one wordcode. */ +/* + * Add one wordcode. + * + * Return the index of the added wordcode. + */ static int ecadd(wordcode c) @@ -402,6 +417,7 @@ ecstrcode(char *s) unsigned val = hasher(s); if ((l = strlen(s) + 1) && l <= 4) { + /* Short string. */ t = has_token(s); wordcode c = (t ? 3 : 2); switch (l) { @@ -412,11 +428,13 @@ ecstrcode(char *s) } return c; } else { + /* Long string. */ Eccstr p, *pp; long cmp; for (pp = &ecstrs; (p = *pp); ) { if (!(cmp = p->nfunc - ecnfunc) && !(cmp = (((long)p->hashval) - ((long)val))) && !(cmp = strcmp(p->str, s))) { + /* Re-use the existing string. */ return p->offs; } pp = (cmp < 0 ? &(p->left) : &(p->right)); @@ -493,7 +511,12 @@ init_parse(void) /* Build eprog. */ -/* careful: copy_ecstr is from arg1 to arg2, unlike memcpy */ +/* + * Copy the strings of s and all its descendants in the binary tree to the + * memory block p. + * + * careful: copy_ecstr is from arg1 to arg2, unlike memcpy + */ static void copy_ecstr(Eccstr s, char *p) diff --git a/Src/zsh.h b/Src/zsh.h index 834142895..82d152bb8 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -832,13 +832,33 @@ struct estate { char *strs; /* strings from prog */ }; +/* + * A binary tree of strings. + * + * Refer to the "Word code." comment at the top of Src/parse.c for details. + */ typedef struct eccstr *Eccstr; - struct eccstr { + /* Child pointers. */ Eccstr left, right; + + /* String; pointer into to estate::strs. */ char *str; - wordcode offs, aoffs; + + /* Wordcode of a long string, as described in the Src/parse.c comment. */ + wordcode offs; + + /* Raw memory offset of str in estate::strs. */ + wordcode aoffs; + + /* + * ### The number of starts and ends of function definitions up to this point. + * + * String reuse may only happen between strings that have the same "nfunc" value. + */ int nfunc; + + /* Hash of str. */ int hashval; }; --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0004-internal-Add-some-comments-around-wordcodes.-No-.patch.txt >From e217f6e22e5c88ed31b1cafac0c75efa372c3ba6 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 21:15:54 +0000 Subject: [PATCH 4/9] internal: Add some comments around wordcodes. No functional change. --- Src/parse.c | 7 +++++++ Src/zsh.h | 8 ++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Src/parse.c b/Src/parse.c index 39d2172d4..666595ef1 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -102,6 +102,13 @@ struct heredocs *hdocs; * The parser now produces word code, reducing memory consumption compared * to the nested structs we had before. * + * Word codes are represented by the "wordcode" type. + * + * Each wordcode variable consists of a "code", in the least-significant bits + * of the value, and "data" in the other bits. The macros wc_code() and wc_data() + * access the "code" and "data" parts of a wordcode. The macros wc_bdata() and + * wc_bld() build wordcodes from code and data. + * * Word code layout: * * WC_END diff --git a/Src/zsh.h b/Src/zsh.h index 82d152bb8..d72c338da 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -866,8 +866,8 @@ struct eccstr { #define EC_DUP 1 #define EC_DUPTOK 2 +/* See comment at the top of Src/parse.c for details. */ #define WC_CODEBITS 5 - #define wc_code(C) ((C) & ((wordcode) ((1 << WC_CODEBITS) - 1))) #define wc_data(C) ((C) >> WC_CODEBITS) #define wc_bdata(D) ((D) << WC_CODEBITS) @@ -896,7 +896,11 @@ struct eccstr { #define WC_AUTOFN 20 #define WC_TRY 21 -/* increment as necessary */ +/* + * Increment as necessary. + * + * If this exceeds 31, increment WC_CODEBITS. + */ #define WC_COUNT 22 #define WCB_END() wc_bld(WC_END, 0) --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0005-internal-Document-the-WC_FUNCDEF-data-layout-for.patch.txt >From edbe98a63a704b0cb2db52f3ed6473f631e04e41 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 21:16:12 +0000 Subject: [PATCH 5/9] internal: Document the WC_FUNCDEF data layout for anonymous functions with arguments (follow-up to 29492) --- Src/parse.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Src/parse.c b/Src/parse.c index 666595ef1..acbf42a9c 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -175,6 +175,10 @@ struct heredocs *hdocs; * - followed by number of patterns for body * - followed by codes for body * - followed by strings for body + * - if number of names is 0, followed by: + * - the offset to the end of the funcdef + * - the number of arguments to the function + * - the arguments to the function * * WC_FOR * - data contains type (list, ...) and offset to after body @@ -1734,8 +1738,9 @@ par_funcdef(int *cmplx) ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p); + /* If it's an anonymous function... */ if (num == 0) { - /* Unnamed function */ + /* ... look for arguments to it. */ int parg = ecadd(0); ecadd(0); while (tok == STRING) { @@ -2110,8 +2115,9 @@ par_simple(int *cmplx, int nr) ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p); + /* If it's an anonymous function... */ if (argc == 0) { - /* Unnamed function */ + /* ... look for arguments to it. */ int parg = ecadd(0); ecadd(0); while (tok == STRING || IS_REDIROP(tok)) { --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0006-internal-Add-some-comments-for-orientation.-No-f.patch.txt >From c4b6bebf6e4e454c6a13c82c916c594cf300791f Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 18 Mar 2020 18:53:11 +0000 Subject: [PATCH 6/9] internal: Add some comments for orientation. No functional change. --- Src/parse.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Src/parse.c b/Src/parse.c index acbf42a9c..8c14aa80b 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1676,7 +1676,7 @@ par_funcdef(int *cmplx) zshlex(); p = ecadd(0); - ecadd(0); + ecadd(0); /* p + 1 */ while (tok == STRING) { if ((*tokstr == Inbrace || *tokstr == '{') && @@ -1688,9 +1688,9 @@ par_funcdef(int *cmplx) num++; zshlex(); } - ecadd(0); - ecadd(0); - ecadd(0); + ecadd(0); /* p + num + 2 */ + ecadd(0); /* p + num + 3 */ + ecadd(0); /* p + num + 4 */ nocorrect = 0; incmdpos = 1; @@ -1728,15 +1728,15 @@ par_funcdef(int *cmplx) ecadd(WCB_END()); ecbuf[p + num + 2] = so - oecssub; - ecbuf[p + num + 3] = ecsoffs - so; - ecbuf[p + num + 4] = ecnpats; - ecbuf[p + 1] = num; + ecbuf[p + num + 3] = ecsoffs - so; /* "length of string table" */ + ecbuf[p + num + 4] = ecnpats; /* "number of patterns for body" */ + ecbuf[p + 1] = num; /* "number of names" */ ecnpats = onp; ecssub = oecssub; ecnfunc++; - ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p); + ecbuf[p] = WCB_FUNCDEF(ecused - 1 - p); /* "offset to after body" */ /* If it's an anonymous function... */ if (num == 0) { --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0007-WC_FUNCDEF-Add-a-placeholder-element.patch.txt >From 745f602c16324a77a38a6d5290c7a11610380069 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 18 Mar 2020 19:57:49 +0000 Subject: [PATCH 7/9] WC_FUNCDEF: Add a placeholder element. --- Config/version.mk | 4 ++-- Src/exec.c | 3 ++- Src/parse.c | 5 +++++ Src/text.c | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Config/version.mk b/Config/version.mk index 6540e4b98..7ecfd35ba 100644 --- a/Config/version.mk +++ b/Config/version.mk @@ -27,5 +27,5 @@ # This must also serve as a shell script, so do not add spaces around the # `=' signs. -VERSION=5.8.0.1-dev -VERSION_DATE='February 15, 2020' +VERSION=5.8.0.2-dev +VERSION_DATE='March 19, 2020' diff --git a/Src/exec.c b/Src/exec.c index cd014ff38..3c3fcfa3e 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -5169,6 +5169,7 @@ execfuncdef(Estate state, Eprog redir_prog) sbeg = *state->pc++; nstrs = *state->pc++; npats = *state->pc++; + (void) *state->pc++; nprg = (end - state->pc); plen = nprg * sizeof(wordcode); @@ -6138,7 +6139,7 @@ stripkshdef(Eprog prog, char *name) int sbeg = pc[2], nstrs = pc[3], nprg, npats = pc[4], plen, len, i; Patprog *pp; - pc += 5; + pc += 6; nprg = end - pc; plen = nprg * sizeof(wordcode); diff --git a/Src/parse.c b/Src/parse.c index 8c14aa80b..eb32d4faf 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -173,6 +173,7 @@ struct heredocs *hdocs; * - followed by offset to first string * - followed by length of string table * - followed by number of patterns for body + * - followed by a placeholder * - followed by codes for body * - followed by strings for body * - if number of names is 0, followed by: @@ -1691,6 +1692,7 @@ par_funcdef(int *cmplx) ecadd(0); /* p + num + 2 */ ecadd(0); /* p + num + 3 */ ecadd(0); /* p + num + 4 */ + ecadd(0); /* p + num + 5 */ nocorrect = 0; incmdpos = 1; @@ -1730,6 +1732,7 @@ par_funcdef(int *cmplx) ecbuf[p + num + 2] = so - oecssub; ecbuf[p + num + 3] = ecsoffs - so; /* "length of string table" */ ecbuf[p + num + 4] = ecnpats; /* "number of patterns for body" */ + ecbuf[p + num + 5] = 0; ecbuf[p + 1] = num; /* "number of names" */ ecnpats = onp; @@ -2053,6 +2056,7 @@ par_simple(int *cmplx, int nr) ecadd(0); ecadd(0); ecadd(0); + ecadd(0); ecnfunc++; ecssub = so = ecsoffs; @@ -2108,6 +2112,7 @@ par_simple(int *cmplx, int nr) ecbuf[p + argc + 2] = so - oecssub; ecbuf[p + argc + 3] = ecsoffs - so; ecbuf[p + argc + 4] = ecnpats; + ecbuf[p + argc + 5] = 0; ecnpats = onp; ecssub = oecssub; diff --git a/Src/text.c b/Src/text.c index 69530ae79..4bf88f2e2 100644 --- a/Src/text.c +++ b/Src/text.c @@ -600,7 +600,7 @@ gettext2(Estate state) n->u._funcdef.end = end; n->u._funcdef.nargs = nargs; state->strs += *state->pc; - state->pc += 3; + state->pc += 4; } } else { state->strs = s->u._funcdef.strs; --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0008-Add-the-function-T-syntax.patch.txt >From c7b30b127659fce57329dbf1b646021454d0f5e3 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 18:00:16 +0000 Subject: [PATCH 8/9] Add the 'function -T' syntax. Config/version.mk was bumped in the previous commit. --- Doc/Zsh/grammar.yo | 13 ++++++++++++- README | 7 +++++++ Src/exec.c | 8 +++++--- Src/parse.c | 11 +++++++++-- Test/E02xtrace.ztst | 25 +++++++++++++++++++++++++ 5 files changed, 58 insertions(+), 6 deletions(-) diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index e028c8512..fa0d72ff5 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -357,7 +357,7 @@ deliberately left unspecified, because historically there was a mismatch between the documented and implemented behaviours. Cf. 20076, 21734/21735, 45075.) ) findex(function) -xitem(tt(function) var(word) ... [ tt(()) ] [ var(term) ] tt({) var(list) tt(})) +xitem(tt(function) [ tt(-T) ] var(word) ... [ tt(()) ] [ var(term) ] tt({) var(list) tt(})) xitem(var(word) ... tt(()) [ var(term) ] tt({) var(list) tt(})) item(var(word) ... tt(()) [ var(term) ] var(command))( where var(term) is one or more newline or tt(;). @@ -367,6 +367,17 @@ are usually only useful for setting traps. The body of the function is the var(list) between the tt({) and tt(}). See noderef(Functions). +The options of tt(function) have the following meanings: + +startitem() +item(-T)( +Enable tracing for this function, as though with tt(functions -T). See the +documentation of the tt(-f) option to the tt(typeset) builtin, in +ifzman(zmanref(zshbuiltins))\ +ifnzman(noderef(Shell Builtin Commands)). +) +enditem() + If the option tt(SH_GLOB) is set for compatibility with other shells, then whitespace may appear between the left and right parentheses when there is a single var(word); otherwise, the parentheses will be treated as diff --git a/README b/README index 2bd5c2179..ae4f788bc 100644 --- a/README +++ b/README @@ -43,6 +43,13 @@ name of an external command. Now it may also be a shell function. Normal command word precedece rules apply, so if you have a function and a command with the same name, the function will be used. +The syntax "function -T { ... }" used to define a function named "-T". +It now defines an anonymous function with single-level tracing enabled --- +same as "function f { ... }; functions -T f; f", but without naming the +function. The syntax "function -T foo { ... }" is similarly affected: it +now defines a function "foo" with tracing enabled; previously it defined +two functions, named "-T" and "foo" (see the MULTI_FUNC_DEF option). + Incompatibilities since 5.7.1 ----------------------------- diff --git a/Src/exec.c b/Src/exec.c index 3c3fcfa3e..2b8e2167f 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -5157,23 +5157,25 @@ execfuncdef(Estate state, Eprog redir_prog) { Shfunc shf; char *s = NULL; - int signum, nprg, sbeg, nstrs, npats, len, plen, i, htok = 0, ret = 0; + int signum, nprg, sbeg, nstrs, npats, do_tracing, len, plen, i, htok = 0, ret = 0; int anon_func = 0; Wordcode beg = state->pc, end; Eprog prog; Patprog *pp; LinkList names; + int tracing_flags; end = beg + WC_FUNCDEF_SKIP(state->pc[-1]); names = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok); sbeg = *state->pc++; nstrs = *state->pc++; npats = *state->pc++; - (void) *state->pc++; + do_tracing = *state->pc++; nprg = (end - state->pc); plen = nprg * sizeof(wordcode); len = plen + (npats * sizeof(Patprog)) + nstrs; + tracing_flags = do_tracing ? PM_TAGGED_LOCAL : 0; if (htok && names) { execsubst(names); @@ -5223,7 +5225,7 @@ execfuncdef(Estate state, Eprog redir_prog) shf = (Shfunc) zalloc(sizeof(*shf)); shf->funcdef = prog; - shf->node.flags = 0; + shf->node.flags = tracing_flags; /* No dircache here, not a directory */ shf->filename = ztrdup(scriptfilename); shf->lineno = diff --git a/Src/parse.c b/Src/parse.c index eb32d4faf..dafc8cca6 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -173,7 +173,7 @@ struct heredocs *hdocs; * - followed by offset to first string * - followed by length of string table * - followed by number of patterns for body - * - followed by a placeholder + * - followed by an integer indicating tracing status * - followed by codes for body * - followed by strings for body * - if number of names is 0, followed by: @@ -1670,6 +1670,7 @@ par_funcdef(int *cmplx) int oecused = ecused, num = 0, onp, p, c = 0; int so, oecssub = ecssub; zlong oldlineno = lineno; + int do_tracing = 0; lineno = 0; nocorrect = 1; @@ -1679,6 +1680,12 @@ par_funcdef(int *cmplx) p = ecadd(0); ecadd(0); /* p + 1 */ + if (tok == STRING && tokstr[0] == Dash && + tokstr[1] == 'T' && !tokstr[2]) { + ++do_tracing; + zshlex(); + } + while (tok == STRING) { if ((*tokstr == Inbrace || *tokstr == '{') && !tokstr[1]) { @@ -1732,7 +1739,7 @@ par_funcdef(int *cmplx) ecbuf[p + num + 2] = so - oecssub; ecbuf[p + num + 3] = ecsoffs - so; /* "length of string table" */ ecbuf[p + num + 4] = ecnpats; /* "number of patterns for body" */ - ecbuf[p + num + 5] = 0; + ecbuf[p + num + 5] = do_tracing; ecbuf[p + 1] = num; /* "number of names" */ ecnpats = onp; diff --git a/Test/E02xtrace.ztst b/Test/E02xtrace.ztst index 795f7e616..d72b2d000 100644 --- a/Test/E02xtrace.ztst +++ b/Test/E02xtrace.ztst @@ -180,3 +180,28 @@ > # traced > echo inner >} + + function -T { echo traced anonymous function } + functions -- -T # no output +1:define traced function: anonymous function +?+(anon):0> echo traced anonymous function +>traced anonymous function + + function -T f { echo traced named function } + functions -- -T # no output + functions f + f +0:define traced function: named function +>f () { +> # traced +> echo traced named function +>} +?+f:0> echo traced named function +>traced named function + + function -T -T { echo trace function literally named "-T" } + -T +0:define traced function: parse test +?+-T:0> echo trace function literally named -T +>trace function literally named -T + --MP_/tI.aMlK5M8vxSBnoqCbKuhK Content-Type: text/plain Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=0009-Add-end-of-options-guard-support-to-function-T.patch.txt >From 0a0e1d5d3191e2a2ef9217ce66c87de60cefa3bf Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 18:11:39 +0000 Subject: [PATCH 9/9] Add end-of-options guard support to 'function -T'. --- README | 23 +++++++++++++++++------ Src/parse.c | 16 ++++++++++++---- Test/E02xtrace.ztst | 22 +++++++++++++++++++++- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/README b/README index ae4f788bc..d08440ce1 100644 --- a/README +++ b/README @@ -43,12 +43,23 @@ name of an external command. Now it may also be a shell function. Normal command word precedece rules apply, so if you have a function and a command with the same name, the function will be used. -The syntax "function -T { ... }" used to define a function named "-T". -It now defines an anonymous function with single-level tracing enabled --- -same as "function f { ... }; functions -T f; f", but without naming the -function. The syntax "function -T foo { ... }" is similarly affected: it -now defines a function "foo" with tracing enabled; previously it defined -two functions, named "-T" and "foo" (see the MULTI_FUNC_DEF option). +The "function" reserved word, used to define functions, gained a new -T option. +That affects syntaxes such as: + +1. "function -T { ... }". It used to define a function named "-T". It +now defines and executes an anonymous function with single-level tracing +enabled --- same as "function f { ... }; functions -T f; f", but without +naming the function. + +2. "function -T foo { ... }". It used to define two functions, named "-T" +and "foo" (see the MULTI_FUNC_DEF option). It now defines a function +"foo" with tracing enabled. + +3. "function -- { ... }". It used to define a function named "--". It +now defines and executes an anonymous function. The "--" is taken to be +an end-of-options guard (same as "ls --"). + +The sh-compatible function definition syntax, "f() { ... }", is unchanged. Incompatibilities since 5.7.1 ----------------------------- diff --git a/Src/parse.c b/Src/parse.c index dafc8cca6..b3650526b 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1680,10 +1680,18 @@ par_funcdef(int *cmplx) p = ecadd(0); ecadd(0); /* p + 1 */ - if (tok == STRING && tokstr[0] == Dash && - tokstr[1] == 'T' && !tokstr[2]) { - ++do_tracing; - zshlex(); + /* Consume an initial (-T), (--), or (-T --). + * Anything else is a literal function name. + */ + if (tok == STRING && tokstr[0] == Dash) { + if (tokstr[1] == 'T' && !tokstr[2]) { + ++do_tracing; + zshlex(); + } + if (tok == STRING && tokstr[0] == Dash && + tokstr[1] == Dash && !tokstr[2]) { + zshlex(); + } } while (tok == STRING) { diff --git a/Test/E02xtrace.ztst b/Test/E02xtrace.ztst index d72b2d000..8b9cc89a8 100644 --- a/Test/E02xtrace.ztst +++ b/Test/E02xtrace.ztst @@ -199,9 +199,29 @@ ?+f:0> echo traced named function >traced named function - function -T -T { echo trace function literally named "-T" } + function -T -- -T { echo trace function literally named "-T" } -T + function -T -- { echo trace anonymous function } + functions -- -- # no output 0:define traced function: parse test ?+-T:0> echo trace function literally named -T >trace function literally named -T +?+(anon):0> echo trace anonymous function +>trace anonymous function + + function -- g { echo g } + g + function -- { echo anonymous } + functions -- -- # no output +0:function end-of-"options" syntax, #1 +>g +>anonymous + + function -- -T { echo runs } + functions -- -- # no output + echo the definition didn\'t execute it + -T +0:function end-of-"options" syntax, #2 +>the definition didn't execute it +>runs --MP_/tI.aMlK5M8vxSBnoqCbKuhK--