From be73026b07decc3990b2a345c42a8f7b74d8f83d Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 18 Mar 2020 17:45:23 +0000 Subject: 45583/0002: internal: Reduce some variables' visibility. No functional change. --- Src/parse.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'Src/parse.c') 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 -- cgit v1.2.3 From 4960699de2fd010598d14d59f4bcd3d9b48ec46b Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 21:14:42 +0000 Subject: 45583/0003: internal: Add some comments around Eccstr. No functional change. --- ChangeLog | 3 +++ Src/parse.c | 31 +++++++++++++++++++++++++++---- Src/zsh.h | 24 ++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 6 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index b73089f91..976d10fd7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-03-22 Daniel Shahaf + * 45583/0003: Src/parse.c, Src/zsh.h: internal: Add some comments + around Eccstr. No functional change. + * 45583/0002: Src/parse.c: internal: Reduce some variables' visibility. No functional change. diff --git a/Src/parse.c b/Src/parse.c index bd974a573..170e07298 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; }; -- cgit v1.2.3 From 338a4a299ad9b5c2e925a5c7ec38d1a6c811c4ed Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 21:15:54 +0000 Subject: 45583/0004: internal: Add some comments around wordcodes. No functional change. --- ChangeLog | 3 +++ Src/parse.c | 7 +++++++ Src/zsh.h | 8 ++++++-- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 976d10fd7..dfaef3a2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-03-22 Daniel Shahaf + * 45583/0004: Src/parse.c, Src/zsh.h: internal: Add some comments + around wordcodes. No functional change. + * 45583/0003: Src/parse.c, Src/zsh.h: internal: Add some comments around Eccstr. No functional change. diff --git a/Src/parse.c b/Src/parse.c index 170e07298..a4f83b573 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) -- cgit v1.2.3 From e37df255c166efdda25d87b9d23f5c492cc02a68 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 21:16:12 +0000 Subject: 45583/0005: internal: Document the WC_FUNCDEF data layout for anonymous functions with arguments (follow-up to 29492) --- ChangeLog | 4 ++++ Src/parse.c | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index dfaef3a2b..fc7b9821f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2020-03-22 Daniel Shahaf + * 45583/0005: Src/parse.c: internal: Document the WC_FUNCDEF + data layout for anonymous functions with arguments (follow-up + to 29492) + * 45583/0004: Src/parse.c, Src/zsh.h: internal: Add some comments around wordcodes. No functional change. diff --git a/Src/parse.c b/Src/parse.c index a4f83b573..6e79f6c4b 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)) { -- cgit v1.2.3 From fd1ef7d770d285dbf12f4b3516ea963a852e5cdd Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 18 Mar 2020 18:53:11 +0000 Subject: 45583/0006: internal: Add some comments for orientation. No functional change. --- ChangeLog | 3 +++ Src/parse.c | 16 ++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index fc7b9821f..6d40cc049 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-03-22 Daniel Shahaf + * 45583/0006: Src/parse.c: internal: Add some comments for + orientation. No functional change. + * 45583/0005: Src/parse.c: internal: Document the WC_FUNCDEF data layout for anonymous functions with arguments (follow-up to 29492) diff --git a/Src/parse.c b/Src/parse.c index 6e79f6c4b..6ca6f33be 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) { -- cgit v1.2.3 From a3c6c5513dcfc25d952735449bf6da476d905184 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 18 Mar 2020 19:57:49 +0000 Subject: 45583/0007: WC_FUNCDEF: Add a placeholder element. --- ChangeLog | 3 +++ Config/version.mk | 4 ++-- Src/exec.c | 3 ++- Src/parse.c | 5 +++++ Src/text.c | 2 +- 5 files changed, 13 insertions(+), 4 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 6d40cc049..fe4102045 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-03-22 Daniel Shahaf + * 45583/0007: Config/version.mk, Src/exec.c, Src/parse.c, + Src/text.c: WC_FUNCDEF: Add a placeholder element. + * 45583/0006: Src/parse.c: internal: Add some comments for orientation. No functional change. 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 6ca6f33be..0111c25b6 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; -- cgit v1.2.3 From 386d9ac8ff961b8f0333d09511e927ab31011658 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 18:00:16 +0000 Subject: 45583/0008: Add the 'function -T' syntax. Config/version.mk was bumped in the previous commit. --- ChangeLog | 3 +++ Doc/Zsh/grammar.yo | 13 ++++++++++++- README | 7 +++++++ Src/exec.c | 8 +++++--- Src/parse.c | 11 +++++++++-- Test/E02xtrace.ztst | 25 +++++++++++++++++++++++++ 6 files changed, 61 insertions(+), 6 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index fe4102045..8f39d7263 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-03-22 Daniel Shahaf + * 45583/0008: Doc/Zsh/grammar.yo, README, Src/exec.c, + Src/parse.c, Test/E02xtrace.ztst: Add the 'function -T' syntax. + * 45583/0007: Config/version.mk, Src/exec.c, Src/parse.c, Src/text.c: WC_FUNCDEF: Add a placeholder element. 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 0111c25b6..0342ee1f8 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 + -- cgit v1.2.3 From aed0cb4408bffe2da89a25054b22144f616bdffe Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Thu, 19 Mar 2020 18:11:39 +0000 Subject: 45583/0009: Add end-of-options guard support to 'function -T'. --- ChangeLog | 3 +++ README | 23 +++++++++++++++++------ Src/parse.c | 16 ++++++++++++---- Test/E02xtrace.ztst | 22 +++++++++++++++++++++- 4 files changed, 53 insertions(+), 11 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 8f39d7263..f1dadc9d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2020-03-22 Daniel Shahaf + * 45583/0009: README, Src/parse.c, Test/E02xtrace.ztst: Add + end-of-options guard support to 'function -T'. + * 45583/0008: Doc/Zsh/grammar.yo, README, Src/exec.c, Src/parse.c, Test/E02xtrace.ztst: Add the 'function -T' syntax. 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 0342ee1f8..08919b2da 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 -- cgit v1.2.3 From 8923d2a61824b0856839d52f3bf52aedb86fd827 Mon Sep 17 00:00:00 2001 From: Mikael Magnusson Date: Thu, 26 Dec 2019 03:54:17 +0100 Subject: Add SHORT_REPEAT option --- ChangeLog | 6 ++++++ Doc/Zsh/grammar.yo | 2 ++ Doc/Zsh/options.yo | 8 ++++++++ Src/lex.c | 2 +- Src/options.c | 1 + Src/parse.c | 2 +- Src/zsh.h | 1 + Test/E01options.ztst | 19 ++++++++++++++----- 8 files changed, 34 insertions(+), 7 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 0d43e8bae..09e89ceaf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2020-04-02 Mikael Magnusson + + * 45142: Doc/Zsh/grammar.yo, Doc/Zsh/options.yo, Src/lex.c, + Src/options.c, Src/parse.c, Src/zsh.h, Test/E01options.ztst: + Add SHORT_REPEAT option + 2020-04-02 Daniel Shahaf * unposted: Test/D02glob.ztst: Make test platform-independent. diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo index fa0d72ff5..a4e0c1121 100644 --- a/Doc/Zsh/grammar.yo +++ b/Doc/Zsh/grammar.yo @@ -428,6 +428,8 @@ else the end of the test will not be recognized. For the tt(for), tt(repeat), tt(case) and tt(select) commands no such special form for the arguments is necessary, but the other condition (the special form of var(sublist) or use of the tt(SHORT_LOOPS) option) still applies. +The tt(SHORT_REPEAT) option is available to enable the short version only +for the tt(repeat) command. startitem() item(tt(if) var(list) tt({) var(list) tt(}) [ tt(elif) var(list) tt({) var(list) tt(}) ] ... [ tt(else {) var(list) tt(}) ])( diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo index fdea51412..2b7637ff4 100644 --- a/Doc/Zsh/options.yo +++ b/Doc/Zsh/options.yo @@ -1377,6 +1377,14 @@ item(tt(SHORT_LOOPS) )( Allow the short forms of tt(for), tt(repeat), tt(select), tt(if), and tt(function) constructs. ) +pindex(SHORT_REPEAT) +pindex(NO_SHORT_REPEAT) +pindex(SHORTREPEAT) +pindex(NOSHORTREPEAT) +item(tt(SHORT_REPEAT))( +Allow the short form tt(repeat) as tt(SHORT_LOOPS) but without enabling +it for the other constructs. +) pindex(SUN_KEYBOARD_HACK) pindex(NO_SUN_KEYBOARD_HACK) pindex(SUNKEYBOARDHACK) diff --git a/Src/lex.c b/Src/lex.c index 1d86da94e..a541defe6 100644 --- a/Src/lex.c +++ b/Src/lex.c @@ -270,7 +270,7 @@ zshlex(void) do { if (inrepeat_) ++inrepeat_; - if (inrepeat_ == 3 && isset(SHORTLOOPS)) + if (inrepeat_ == 3 && (isset(SHORTLOOPS) || isset(SHORTREPEAT))) incmdpos = 1; tok = gettok(); } while (tok != ENDINPUT && exalias()); diff --git a/Src/options.c b/Src/options.c index 08ba71917..7586d21d2 100644 --- a/Src/options.c +++ b/Src/options.c @@ -248,6 +248,7 @@ static struct optname optns[] = { {{NULL, "shnullcmd", OPT_EMULATE|OPT_BOURNE}, SHNULLCMD}, {{NULL, "shoptionletters", OPT_EMULATE|OPT_BOURNE}, SHOPTIONLETTERS}, {{NULL, "shortloops", OPT_EMULATE|OPT_NONBOURNE},SHORTLOOPS}, +{{NULL, "shortrepeat", OPT_EMULATE}, SHORTREPEAT}, {{NULL, "shwordsplit", OPT_EMULATE|OPT_BOURNE}, SHWORDSPLIT}, {{NULL, "singlecommand", OPT_SPECIAL}, SINGLECOMMAND}, {{NULL, "singlelinezle", OPT_KSH}, SINGLELINEZLE}, diff --git a/Src/parse.c b/Src/parse.c index 08919b2da..10c9b4c29 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1593,7 +1593,7 @@ par_repeat(int *cmplx) if (tok != ZEND) YYERRORV(oecused); zshlex(); - } else if (unset(SHORTLOOPS)) { + } else if (unset(SHORTLOOPS) && unset(SHORTREPEAT)) { YYERRORV(oecused); } else par_save_list1(cmplx); diff --git a/Src/zsh.h b/Src/zsh.h index d72c338da..1f2d774a1 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -2508,6 +2508,7 @@ enum { SHNULLCMD, SHOPTIONLETTERS, SHORTLOOPS, + SHORTREPEAT, SHWORDSPLIT, SINGLECOMMAND, SINGLELINEZLE, diff --git a/Test/E01options.ztst b/Test/E01options.ztst index cfe2c75cc..70736f444 100644 --- a/Test/E01options.ztst +++ b/Test/E01options.ztst @@ -1109,15 +1109,22 @@ F:Regression test for workers/41811 eval 'for f (word1 word2) print $f' eval 'repeat 3 print nonsense' } - unsetopt shortloops - print option unset + unsetopt shortloops shortrepeat + print shortloops and shortrepeat unset + fn + setopt shortrepeat + print shortrepeat set fn setopt shortloops - print option set + print shortloops set fn 0:SHORT_LOOPS option ->option unset ->option set +>shortloops and shortrepeat unset +>shortrepeat set +>nonsense +>nonsense +>nonsense +>shortloops set >foo >bar >word1 @@ -1127,6 +1134,8 @@ F:Regression test for workers/41811 >nonsense ?(eval):1: parse error near `print' ?(eval):1: parse error near `print' +?(eval):1: parse error near `print' +?(eval):1: parse error near `print' ?(eval):1: parse error near `print' fn() { print -l $*; } -- cgit v1.2.3 From d4da2c73f0a1767d6562e735ede40251f9f4366b Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Sun, 22 Mar 2020 08:09:09 +0000 Subject: 47300: Document the EC_NODUP, EC_DUP, EC_DUPTOK triplet. All uses reviewed; no functional change. --- ChangeLog | 5 +++++ Src/parse.c | 7 +++++++ Src/zsh.h | 23 ++++++++++++++++++++--- 3 files changed, 32 insertions(+), 3 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 06f1aab9f..9df308c54 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2020-08-08 Daniel Shahaf + + * 47300: Src/parse.c, Src/zsh.h: Document the EC_NODUP, EC_DUP, + EC_DUPTOK triplet. + 2020-08-08 Mikael Magnusson * unposted: Completion/BSD/Command/_kdump, diff --git a/Src/parse.c b/Src/parse.c index 10c9b4c29..b09c7989a 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -2828,6 +2828,13 @@ freeeprog(Eprog p) } } +/* + * dup is of type 'enum ec_dup_t'. + * + * If tokflag is not NULL, *tokflag will be set to 1 if the string contains + * tokens and to 0 otherwise. + */ + /**/ char * ecgetstr(Estate s, int dup, int *tokflag) diff --git a/Src/zsh.h b/Src/zsh.h index a97e83192..94f5099c6 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -862,9 +862,26 @@ struct eccstr { int hashval; }; -#define EC_NODUP 0 -#define EC_DUP 1 -#define EC_DUPTOK 2 +/* + * Values for the "dup" parameter to ecgetstr(). + */ +enum ec_dup_t { + /* + * Make no promises about how the return value is allocated, except that + * the caller does not need to explicitly free it. It might be heap allocated, + * a static string, or anything in between. + */ + EC_NODUP = 0, + + /* Allocate the return value from the heap. */ + EC_DUP = 1, + + /* + * If the string contains tokens (as indicated by the least significant bit + * of the wordcode), behave as EC_DUP; otherwise, as EC_NODUP. + */ + EC_DUPTOK = 2 +}; /* See comment at the top of Src/parse.c for details. */ #define WC_CODEBITS 5 -- cgit v1.2.3 From daa208e90763d304dc1d554a834d0066e0b9937c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 10 Aug 2021 09:19:32 +0100 Subject: 49269: Fix "[ ! -o ]". This should detect "-o" as non-empty string; "-a" was alrady working. Update the test. --- ChangeLog | 6 ++++++ Src/parse.c | 2 +- Test/C02cond.ztst | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 4690121fc..b7ba668f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2021-08-10 Peter Stephenson + + * 49269: Src/parse.c, Test/C02cond.ztst: "[ ! -o ]" should + detect "-o" as a non-empty string and return status 1. Update + test to reflect this. + 2021-07-30 dana * github #77: Stavros Ntentos: Completion/X/Command/_sublimetext: diff --git a/Src/parse.c b/Src/parse.c index b09c7989a..be26112a5 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -2509,7 +2509,7 @@ par_cond_2(void) * In "test" compatibility mode, "! -a ..." and "! -o ..." * are treated as "[string] [and] ..." and "[string] [or] ...". */ - if (!(n_testargs > 1 && (check_cond(*testargs, "a") || + if (!(n_testargs > 2 && (check_cond(*testargs, "a") || check_cond(*testargs, "o")))) { condlex(); diff --git a/Test/C02cond.ztst b/Test/C02cond.ztst index 5b105b2a0..4366b4142 100644 --- a/Test/C02cond.ztst +++ b/Test/C02cond.ztst @@ -380,7 +380,7 @@ F:scenario if you encounter it. >0 >0 >1 ->0 +>1 >0 >0 >1 -- cgit v1.2.3 From a675d058db7587eaf2f95da3e6d14fdacf01a7b0 Mon Sep 17 00:00:00 2001 From: Marlon Richert Date: Mon, 6 Sep 2021 14:16:18 -0700 Subject: 49378: skip check for collision of aliases and functions when NO_EXEC --- ChangeLog | 3 +++ Src/parse.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 885b7ed91..2a6b68368 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2021-09-06 Bart Schaefer + * Marlon Richert: 49378: Src/parse.c: skip check for collision + of aliases and functions when NO_EXEC + * 49282: set $0 correctly when calling functions from hooks * 49266: fix segfault on metacharacters in long job texts diff --git a/Src/parse.c b/Src/parse.c index be26112a5..10d193ba1 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -2052,7 +2052,7 @@ par_simple(int *cmplx, int nr) /* Error if preceding assignments */ if (assignments || postassigns) YYERROR(oecused); - if (hasalias && !isset(ALIASFUNCDEF) && argc && + if (isset(EXECOPT) && hasalias && !isset(ALIASFUNCDEF) && argc && hasalias != input_hasalias()) { zwarn("defining function based on alias `%s'", hasalias); YYERROR(oecused); -- cgit v1.2.3 From 0b3b25979478ed8af7b337b9ed6739fd69dfeee8 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 5 Oct 2021 16:45:55 +0100 Subject: 49433: Don't assume EPROG references are bounded by function depth. We use references for efficient function copy, so there is no useful limit any more. --- ChangeLog | 5 +++++ Src/parse.c | 4 ---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 62470ba0b..d1ca22d26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-10-05 Peter Stephenson + + * 49433: Src/parse.c: Assuming EPROG references are bounded by + function depth is incorrect as we have efficient function copy. + 2021-10-04 Bart Schaefer * 49456: Doc/Zsh/mod_private.yo, Doc/Zsh/params.yo, diff --git a/Src/parse.c b/Src/parse.c index 10d193ba1..d612b7e17 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -2811,10 +2811,6 @@ freeeprog(Eprog p) DPUTS(p->nref > 0 && (p->flags & EF_HEAP), "Heap EPROG has nref > 0"); 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(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++) freepatprog(*pp); -- cgit v1.2.3