zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <p.w.stephenson@ntlworld.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: Minor bug(s) with NO_MULTI_FUNC_DEF
Date: Tue, 31 May 2022 10:03:17 +0100 (BST)	[thread overview]
Message-ID: <1980097513.514587.1653987797049@mail2.virginmedia.com> (raw)
In-Reply-To: <CAH+w=7Y7Q8H9YVEjNd8gsE=5LzpRo74DvVAeK9ORguuuhr00kg@mail.gmail.com>

> On 30 May 2022 at 21:31 Bart Schaefer <schaefer@brasslantern.com> wrote:
> Even with that option set, "functions" outputs multifuncdef syntax.
> 
> % setopt nomultifuncdef
> % foo() {
> function foo1 foo2 foo3 { echo $0 }
> function> }
> % functions foo
> foo () {
>     foo1 foo2 foo3 () {
>         echo $0
>     }
> }

So the question is, is it time to output all functions (except anonymous)
using the other syntax, which is the one we recommend anyway?  Updating
the tests as below suggests this is basically OK; I suppose we have to
think up interesting edge cases.  I don't see a good argument for
doing it differently depending on the option setting.

From my point, actually, it's a step in the right direction --- I
just tried

eval "$(functions)"

before and after the change; before it gave me

zsh: defining function based on alias `d'
zsh: parse error near `()'

whereas after it's silent.  I presume the latter error is a consequence
of the previous warning, but I haven't looked further. Of course,
silent doesn't mean the same as completely functional.

Strictly, we can print anonymous functions the other way, too, but it
somehow seems less natural, as well as reasonable to have some visual
discriminator, so I've left them as "()" here.

> As an aside, something like this:
> 
> TRAP{HUP,INT,QUIT,TERM} () { print -u2 Got $1 }
> 
> bypasses the nomultifuncdef syntax check and successfully defines all
> four functions.

We could probably document our way out here.  It is a single command
line word in origin so the intention must be the obvious one.

pws

diff --git a/Src/hashtable.c b/Src/hashtable.c
index bb165505e..74e838829 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -942,10 +942,11 @@ printshfuncnode(HashNode hn, int printflags)
 	putchar('\n');
 	return;
     }
- 
+
+    printf("function ");
     quotedzputs(f->node.nam, stdout);
     if (f->funcdef || f->node.flags & PM_UNDEFINED) {
-	printf(" () {\n");
+	printf(" {\n");
 	zoutputtab(stdout);
 	if (f->node.flags & PM_UNDEFINED) {
 	    printf("%c undefined\n", hashchar);
@@ -983,7 +984,7 @@ printshfuncnode(HashNode hn, int printflags)
 	}
 	printf("\n}");
     } else {
-	printf(" () { }");
+	printf(" { }");
     }
     if (f->redir) {
 	t = getpermtext(f->redir, NULL, 1);
diff --git a/Src/text.c b/Src/text.c
index 5cd7685fd..89de27ea5 100644
--- a/Src/text.c
+++ b/Src/text.c
@@ -578,11 +578,16 @@ gettext2(Estate state)
 		Wordcode end = p + WC_FUNCDEF_SKIP(code);
 		int nargs = *state->pc++;
 
-		taddlist(state, nargs);
-		if (nargs)
+		if (nargs) {
+		    taddstr("function ");
+		    taddlist(state, nargs);
 		    taddstr(" ");
+		} else {
+		    /* Anonymous function */
+		    taddstr("() ");
+		}
 		if (tjob) {
-		    taddstr("() { ... }");
+		    taddstr("{ ... }");
 		    state->pc = end;
 		    if (!nargs) {
 			/*
@@ -594,7 +599,7 @@ gettext2(Estate state)
 		    }
 		    stack = 1;
 		} else {
-		    taddstr("() {");
+		    taddstr("{");
 		    tindent++;
 		    taddnl(1);
 		    n = tpush(code, 1);
diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
index 0312fe94e..719a43c3d 100644
--- a/Test/A01grammar.ztst
+++ b/Test/A01grammar.ztst
@@ -80,7 +80,7 @@
   functions -x3 fn
   fn
 0:End of sublist containing ! with no command
->fn () {
+>function fn {
 >   : && !
 >   :
 >}
@@ -95,7 +95,7 @@
   functions -x2 fn
   fn
 0:exclamation marks without following commands
->fn () {
+>function fn {
 >  ! {
 >    !
 >  } && ! (
@@ -473,19 +473,19 @@
   fn3() { ( echo foo; ) }
   functions fn1 fn2 fn3
 0:Output of syntactic structures with and without always blocks
->fn1 () {
+>function fn1 {
 >	{
 >		echo foo
 >	}
 >}
->fn2 () {
+>function fn2 {
 >	{
 >		echo foo
 >	} always {
 >		echo bar
 >	}
 >}
->fn3 () {
+>function fn3 {
 >	(
 >		echo foo
 >	)
@@ -776,7 +776,7 @@ F:Note that the behaviour of 'exit' inside try-list inside a function is unspeci
   fn abecedinarian
   fn xylophone)
 0: case word handling in sh emulation (SH_GLOB parentheses)
->fn () {
+>function fn {
 >	case $1 in
 >		(one | two | three) print Matched $1 ;;
 >		(fo* | fi* | si*) print Pattern matched $1 ;;
@@ -846,7 +846,7 @@ F:Note that the behaviour of 'exit' inside try-list inside a function is unspeci
   which fn
   fn
 0:Long case with parsed alternatives turned back into text
->fn () {
+>function fn {
 >	typeset ac_file="the else branch" 
 >	case $ac_file in
 >		(*.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj)  ;;
diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst
index 17f6dfa29..855c44782 100644
--- a/Test/A04redirect.ztst
+++ b/Test/A04redirect.ztst
@@ -230,7 +230,7 @@
   eval $'fn-varid() { print {\x18}<<0 }'
   { which -x2 fn-varid; fn-varid } | tr $'\x18' '?'
 0:Regression test for off-by-one in varid check
->fn-varid () {
+>function fn-varid {
 >  print {?} <<0
 >0
 >}
@@ -575,7 +575,7 @@
 
   which redirfn
 0:text output of function with redirections
->redirfn () {
+>function redirfn {
 >	local var
 >	read var
 >	print I want to tell you about $var
@@ -653,7 +653,7 @@
   fn-two-heres
   print $functions[fn-two-heres]
 0:Two here-documents in a line are shown correctly.
->fn-two-heres () {
+>function fn-two-heres {
 >  cat <<x <<y
 >foo
 >x
@@ -679,7 +679,7 @@
   which fn-here-pipe
 0:Combination of HERE-document and |&
 >FOO
->fn-here-pipe () {
+>function fn-here-pipe {
 >	cat <<HERE 2>&1 | cat
 >FOO
 >HERE
diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst
index d95ee363c..22c84aaec 100644
--- a/Test/A05execution.ztst
+++ b/Test/A05execution.ztst
@@ -272,7 +272,7 @@ F:anonymous function, and a descriptor leak when backgrounding a pipeline
 0:
 >No output yet
 >Autoloaded ksh style
->autoload_redir () {
+>function autoload_redir {
 >	print Autoloaded ksh style
 >} > autoload.log
 
diff --git a/Test/B02typeset.ztst b/Test/B02typeset.ztst
index 8b3988151..7ec43adee 100644
--- a/Test/B02typeset.ztst
+++ b/Test/B02typeset.ztst
@@ -797,10 +797,10 @@
   fn2() { typeset assignfirst=(why not); }
   which -x2 fn2
 0:text output from typeset
->fn () {
+>function fn {
 >  typeset foo bar thing=this stuff=(that other) more=woevva 
 >}
->fn2 () {
+>function fn2 {
 >  typeset assignfirst=(why not) 
 >}
 
diff --git a/Test/C02cond.ztst b/Test/C02cond.ztst
index 4366b4142..502365d05 100644
--- a/Test/C02cond.ztst
+++ b/Test/C02cond.ztst
@@ -355,7 +355,7 @@ F:scenario if you encounter it.
   }
   which crashme
 0:Regression test for examining code with regular expression match
->crashme () {
+>function crashme {
 >	if [[ $1 =~ ^http:* ]]
 >	then
 >		url=${1#*=} 
@@ -424,7 +424,7 @@ F:scenario if you encounter it.
   fn() { [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]] }
   which -x2 fn
 0: = and == appear as input
->fn () {
+>function fn {
 >  [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]]
 >}
 
diff --git a/Test/C03traps.ztst b/Test/C03traps.ztst
index f120809a7..6483494d3 100644
--- a/Test/C03traps.ztst
+++ b/Test/C03traps.ztst
@@ -101,13 +101,13 @@
   }
   fn1
 0: Nested TRAPINT, not triggered
->TRAPINT () {
+>function TRAPINT {
 >	print INT1
 >}
->TRAPINT () {
+>function TRAPINT {
 >	print INT2
 >}
->TRAPINT () {
+>function TRAPINT {
 >	print INT1
 >}
 
@@ -391,10 +391,10 @@
    fn2
    fn1')
 0:POSIX_TRAPS option
->TRAPEXIT () {
+>function TRAPEXIT {
 >	print Exited
 >}
->TRAPEXIT () {
+>function TRAPEXIT {
 >	print No, really exited
 >}
 >No, really exited
diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst
index af469c527..2f8ee1fe3 100644
--- a/Test/C04funcdef.ztst
+++ b/Test/C04funcdef.ztst
@@ -259,7 +259,7 @@
   }
   functions fn
 0:Text representation of anonymous function with arguments
->fn () {
+>function fn {
 >	() {
 >		print Anonymous function 1 $*
 >	} with args
@@ -321,7 +321,7 @@
  barexpansion() { print This is the correct output.; }
  funcwithalias
 0:Alias expanded in command substitution does not appear expanded in text
->funcwithalias () {
+>function funcwithalias {
 >	echo $(fooalias)
 >}
 >This is the correct output.
@@ -348,7 +348,7 @@
   )
 0:autoload containing eval
 >oops was successfully autoloaded
->oops () {
+>function oops {
 >  print oops was successfully autoloaded
 >}
 
diff --git a/Test/C05debug.ztst b/Test/C05debug.ztst
index 9a8df1dad..3a428cba0 100644
--- a/Test/C05debug.ztst
+++ b/Test/C05debug.ztst
@@ -137,7 +137,7 @@
 >6: 'x=y '
 >7: 'print $x'
 >y
->8: 'fn2 () {
+>8: 'function fn2 {
 >	echo wow
 >}'
 >9: 'fn2'
diff --git a/Test/E02xtrace.ztst b/Test/E02xtrace.ztst
index 56bc20f1a..59cdfdc5b 100644
--- a/Test/E02xtrace.ztst
+++ b/Test/E02xtrace.ztst
@@ -164,19 +164,19 @@
     "
   done
 0:a function that redefines itself preserves tracing
->f () {
+>function f {
 >	# traced
 >	echo inner
 >}
->foo-bar () {
+>function foo-bar {
 >	# traced
 >	echo inner
 >}
->$'\M-c\M-\C-C\M-\C-L' () {
+>function $'\M-c\M-\C-C\M-\C-L' {
 >	# traced
 >	echo inner
 >}
->$'ba\C-@z' () {
+>function $'ba\C-@z' {
 >	# traced
 >	echo inner
 >}
@@ -192,7 +192,7 @@
  functions f
  f
 0:define traced function: named function
->f () {
+>function f {
 >	# traced
 >	echo traced named function
 >}


  reply	other threads:[~2022-05-31  9:05 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-05-30 20:31 Bart Schaefer
2022-05-31  9:03 ` Peter Stephenson [this message]
2022-05-31 17:07   ` Bart Schaefer
2022-05-31 17:14     ` Bart Schaefer
2022-06-06  8:45       ` Peter Stephenson
2022-06-06 15:53         ` Peter Stephenson
2022-06-02 10:23   ` Daniel Shahaf
2022-06-02 15:23     ` Bart Schaefer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1980097513.514587.1653987797049@mail2.virginmedia.com \
    --to=p.w.stephenson@ntlworld.com \
    --cc=zsh-workers@zsh.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).