about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--Doc/Zsh/grammar.yo13
-rw-r--r--README7
-rw-r--r--Src/exec.c8
-rw-r--r--Src/parse.c11
-rw-r--r--Test/E02xtrace.ztst25
6 files changed, 61 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index fe4102045..8f39d7263 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2020-03-22  Daniel Shahaf  <d.s@daniel.shahaf.name>
 
+	* 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
+