ksh: support "function name()"

classic Classic list List threaded Threaded
10 messages Options
Reply | Threaded
Open this post in threaded view
|

ksh: support "function name()"

Jeremie Courreges-Anglas-2

We have a few ports (~12) patched because of shell script constructs
like

  function usage()
  {

which are rejected by our ksh.  Indeed ksh only supports either

  usage()
  {

or

  function usage
  {

Both bash and zsh also allow an optional "()".  The diff below
implements the missing bits.

Since the "reject = true;" mechanism bypasses yylex(), I have to
pass token() the same flags as with the musthave('{') call below.

ok?


Index: ksh.1
===================================================================
RCS file: /d/cvs/src/bin/ksh/ksh.1,v
retrieving revision 1.208
diff -u -p -r1.208 ksh.1
--- ksh.1 26 Nov 2019 22:49:01 -0000 1.208
+++ ksh.1 27 Dec 2019 12:27:37 -0000
@@ -679,7 +679,7 @@ The exit status of a
 statement is the last exit status of the
 .Ar list
 in the body of the loop; if the body is not executed, the exit status is zero.
-.It Xo Ic function Ar name
+.It Xo Ic function Ar name Op ()
 .No { Ar list ; No }
 .Xc
 Defines the function
Index: syn.c
===================================================================
RCS file: /d/cvs/src/bin/ksh/syn.c,v
retrieving revision 1.39
diff -u -p -r1.39 syn.c
--- syn.c 24 Apr 2018 08:25:16 -0000 1.39
+++ syn.c 27 Dec 2019 11:25:41 -0000
@@ -555,6 +555,12 @@ function_body(char *name,
  * an open-brace.
  */
  if (ksh_func) {
+ /* allow optional () after function name */
+ if (token(CONTIN|KEYWORD|ALIAS) == '(')
+ musthave(')', 0);
+ else
+ reject = true;
+
  musthave('{', CONTIN|KEYWORD|ALIAS); /* } */
  reject = true;
  }


--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply | Threaded
Open this post in threaded view
|

Re: ksh: support "function name()"

Andras Farkas
If this diff gets accepted, in ksh's man page, you'll probably have to
change the following line as it's not entirely disambiguous how a
function would behave if it had both 'function' and '()' where it was
defined:
"Functions defined with the function reserved word are treated
differently in the following ways from functions defined with the ()
notation:"
Notably, would someone learning ksh realise 'function funname()' isn't
being defined with both notations at once?
Examples might be:
"Functions defined with the function reserved word are treated
differently in the following ways from functions defined solely with
the () notation:"
"Functions defined with the function reserved word are treated
differently in the following ways from functions defined without it:"

That said, I personally think to define a function with both
'function' and '()' is a genuine syntax error.

On Sat, Dec 28, 2019 at 8:42 AM Jeremie Courreges-Anglas <[hidden email]> wrote:

>
>
> We have a few ports (~12) patched because of shell script constructs
> like
>
>   function usage()
>   {
>
> which are rejected by our ksh.  Indeed ksh only supports either
>
>   usage()
>   {
>
> or
>
>   function usage
>   {
>
> Both bash and zsh also allow an optional "()".  The diff below
> implements the missing bits.
>
> Since the "reject = true;" mechanism bypasses yylex(), I have to
> pass token() the same flags as with the musthave('{') call below.
>
> ok?
>
>
> Index: ksh.1
> ===================================================================
> RCS file: /d/cvs/src/bin/ksh/ksh.1,v
> retrieving revision 1.208
> diff -u -p -r1.208 ksh.1
> --- ksh.1       26 Nov 2019 22:49:01 -0000      1.208
> +++ ksh.1       27 Dec 2019 12:27:37 -0000
> @@ -679,7 +679,7 @@ The exit status of a
>  statement is the last exit status of the
>  .Ar list
>  in the body of the loop; if the body is not executed, the exit status is zero.
> -.It Xo Ic function Ar name
> +.It Xo Ic function Ar name Op ()
>  .No { Ar list ; No }
>  .Xc
>  Defines the function
> Index: syn.c
> ===================================================================
> RCS file: /d/cvs/src/bin/ksh/syn.c,v
> retrieving revision 1.39
> diff -u -p -r1.39 syn.c
> --- syn.c       24 Apr 2018 08:25:16 -0000      1.39
> +++ syn.c       27 Dec 2019 11:25:41 -0000
> @@ -555,6 +555,12 @@ function_body(char *name,
>          * an open-brace.
>          */
>         if (ksh_func) {
> +               /* allow optional () after function name */
> +               if (token(CONTIN|KEYWORD|ALIAS) == '(')
> +                       musthave(')', 0);
> +               else
> +                       reject = true;
> +
>                 musthave('{', CONTIN|KEYWORD|ALIAS); /* } */
>                 reject = true;
>         }
>
>
> --
> jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE
>

Reply | Threaded
Open this post in threaded view
|

Re: ksh: support "function name()"

Klemens Nanni-2
In reply to this post by Jeremie Courreges-Anglas-2
On Sat, Dec 28, 2019 at 02:40:27PM +0100, Jeremie Courreges-Anglas wrote:

> We have a few ports (~12) patched because of shell script constructs
> like
>
>   function usage()
>   {
>
> which are rejected by our ksh.  Indeed ksh only supports either
>
>   usage()
>   {
>
> or
>
>   function usage
>   {
>
> Both bash and zsh also allow an optional "()".  The diff below
> implements the missing bits.
Thanks, I wanted this as well for some time.

> Since the "reject = true;" mechanism bypasses yylex(), I have to
> pass token() the same flags as with the musthave('{') call below.
>
> ok?
Defining, listing and undefining works.  As per the differences between
`function name' and `name()', your new `function name()' behaves like
the former.  This should be clarified in the manual.

The Functions paragraph starts with repeating the currently two possible
forms, either remove the duplicate work there or adjust accordingly.  It
also goes into detail about the differences, e.g. `$0' being different;
strictly speaking this must be clarified as well, since the new form
`funtion name()' now satisfies both criteria: "Functions defined with
the function reserved word" and "functions defined with the () notation".

> Index: ksh.1
> ===================================================================
> RCS file: /d/cvs/src/bin/ksh/ksh.1,v
> retrieving revision 1.208
> diff -u -p -r1.208 ksh.1
> --- ksh.1 26 Nov 2019 22:49:01 -0000 1.208
> +++ ksh.1 27 Dec 2019 12:27:37 -0000
> @@ -679,7 +679,7 @@ The exit status of a
>  statement is the last exit status of the
>  .Ar list
>  in the body of the loop; if the body is not executed, the exit status is zero.
> -.It Xo Ic function Ar name
> +.It Xo Ic function Ar name Op ()
There must be no space between `name' and `['.

>  .No { Ar list ; No }
>  .Xc
>  Defines the function

Reply | Threaded
Open this post in threaded view
|

Re: ksh: support "function name()"

Mark Kettenis
In reply to this post by Jeremie Courreges-Anglas-2
> From: Jeremie Courreges-Anglas <[hidden email]>
> Date: Sat, 28 Dec 2019 14:40:27 +0100
>
> We have a few ports (~12) patched because of shell script constructs
> like
>
>   function usage()
>   {

What is the #! for those scripts?

> which are rejected by our ksh.  Indeed ksh only supports either
>
>   usage()
>   {
>
> or
>
>   function usage
>   {
>
> Both bash and zsh also allow an optional "()".  The diff below
> implements the missing bits.

But our ksh isn't bash or zsh!

Are there other ksh implementations that have this "feature"?

> Since the "reject = true;" mechanism bypasses yylex(), I have to
> pass token() the same flags as with the musthave('{') call below.
>
> ok?
>
>
> Index: ksh.1
> ===================================================================
> RCS file: /d/cvs/src/bin/ksh/ksh.1,v
> retrieving revision 1.208
> diff -u -p -r1.208 ksh.1
> --- ksh.1 26 Nov 2019 22:49:01 -0000 1.208
> +++ ksh.1 27 Dec 2019 12:27:37 -0000
> @@ -679,7 +679,7 @@ The exit status of a
>  statement is the last exit status of the
>  .Ar list
>  in the body of the loop; if the body is not executed, the exit status is zero.
> -.It Xo Ic function Ar name
> +.It Xo Ic function Ar name Op ()
>  .No { Ar list ; No }
>  .Xc
>  Defines the function
> Index: syn.c
> ===================================================================
> RCS file: /d/cvs/src/bin/ksh/syn.c,v
> retrieving revision 1.39
> diff -u -p -r1.39 syn.c
> --- syn.c 24 Apr 2018 08:25:16 -0000 1.39
> +++ syn.c 27 Dec 2019 11:25:41 -0000
> @@ -555,6 +555,12 @@ function_body(char *name,
>   * an open-brace.
>   */
>   if (ksh_func) {
> + /* allow optional () after function name */
> + if (token(CONTIN|KEYWORD|ALIAS) == '(')
> + musthave(')', 0);
> + else
> + reject = true;
> +
>   musthave('{', CONTIN|KEYWORD|ALIAS); /* } */
>   reject = true;
>   }
>
>
> --
> jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE
>
>

Reply | Threaded
Open this post in threaded view
|

Re: ksh: support "function name()"

Klemens Nanni-2
In reply to this post by Andras Farkas
On Sat, Dec 28, 2019 at 09:53:28AM -0500, Andras Farkas wrote:
> That said, I personally think to define a function with both
> 'function' and '()' is a genuine syntax error.
Right now it definitely is a syntax error, what that is what this diff
tries to fix ;-)

I think compatibility to other Bourne-like shells is preffered to
pedantic behaviour here, especially since it comes at no cost.

Reply | Threaded
Open this post in threaded view
|

Re: ksh: support "function name()"

Klemens Nanni-2
In reply to this post by Mark Kettenis
On Sat, Dec 28, 2019 at 04:07:02PM +0100, Mark Kettenis wrote:
> Are there other ksh implementations that have this "feature"?
MirBSD's ksh allows all three forms but treats `function name()' like
`name()', that is $0 stays the same and will not be set to the funtion's
name:

        $ echo $KSH_VERSION
        @(#)MIRBSD KSH R57 2019/03/01
        $ function f { echo $0; }
        $ f2() { echo $0; }
        $ function f3() { echo $0; }
        $ typeset -f
        function f {
                \echo $0
        }
        f2() {
                \echo $0
        }
        f3() {
                \echo $0
        }
        $ f
        f
        $ f2
        mksh
        $ f3
        mksh

Reply | Threaded
Open this post in threaded view
|

Re: ksh: support "function name()"

Andras Farkas
In reply to this post by Mark Kettenis
On Sat, Dec 28, 2019 at 10:08 AM Mark Kettenis <[hidden email]> wrote:
> [snip]
> Are there other ksh implementations that have this "feature"?
As for this question, I can at least confirm that no version of ksh93 has it.

Reply | Threaded
Open this post in threaded view
|

Re: ksh: support "function name()"

Jeremie Courreges-Anglas-2
In reply to this post by Klemens Nanni-2
On Sat, Dec 28 2019, Klemens Nanni <[hidden email]> wrote:
> On Sat, Dec 28, 2019 at 04:07:02PM +0100, Mark Kettenis wrote:
>> Are there other ksh implementations that have this "feature"?
> MirBSD's ksh allows all three forms but treats `function name()' like
> `name()', that is $0 stays the same and will not be set to the funtion's
> name:

Bah, I think I understand why this was chosen.  bash functions declared
with "function name" or "function name()" aren't special.  Probably we
should do the same.  I'm postponing this for now, thanks for the
feedback so far.

> $ echo $KSH_VERSION
> @(#)MIRBSD KSH R57 2019/03/01
> $ function f { echo $0; }
> $ f2() { echo $0; }
> $ function f3() { echo $0; }
> $ typeset -f
> function f {
> \echo $0
> }
> f2() {
> \echo $0
> }
> f3() {
> \echo $0
> }
> $ f
> f
> $ f2
> mksh
> $ f3
> mksh
>

--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply | Threaded
Open this post in threaded view
|

Re: ksh: support "function name()"

Klemens Nanni-2
On Tue, Jan 07, 2020 at 06:47:16PM +0100, Jeremie Courreges-Anglas wrote:
> Bah, I think I understand why this was chosen.  bash functions declared
> with "function name" or "function name()" aren't special.  Probably we
> should do the same.  I'm postponing this for now, thanks for the
> feedback so far.
I think we should keep differences between the two forms, having $0
expand to the function name is a nice feature I do use.

Reply | Threaded
Open this post in threaded view
|

Re: ksh: support "function name()"

Jeremie Courreges-Anglas-2
On Tue, Jan 07 2020, Klemens Nanni <[hidden email]> wrote:
> On Tue, Jan 07, 2020 at 06:47:16PM +0100, Jeremie Courreges-Anglas wrote:
>> Bah, I think I understand why this was chosen.  bash functions declared
>> with "function name" or "function name()" aren't special.  Probably we
>> should do the same.

... the same as mksh.  Sorry, that was misleading.

>> I'm postponing this for now, thanks for the
>> feedback so far.
> I think we should keep differences between the two forms, having $0
> expand to the function name is a nice feature I do use.

I do not intend to change the existing behavior of "function name".

--
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE