[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    Re: [PATCH] ash: add support for bash 'function' keyword
From:       Denys Vlasenko <vda.linux () googlemail ! com>
Date:       2015-11-04 18:33:35
Message-ID: CAK1hOcP_inbEAK00FKvwqii2gmC7xBsaU_wrkA7AgthUtLjn8g () mail ! gmail ! com
[Download RAW message or body]

Applied, thanks!

On Tue, Nov 3, 2015 at 10:42 AM, Ron Yorston <rmy@pobox.com> wrote:
> Where the POSIX shell allows functions to be defined as:
>
>    name () compound-command [ redirections ]
>
> bash adds the alternative syntax:
>
>    function name [()] compound-command [ redirections ]
>
> Implement this in ash's bash compatibility mode.  Most compound
> commands work (for/while/until/if/case/[[]]/{}); one exception is:
>
>    function f (echo "no way!")
>
> The other two variants work:
>
>    f() (echo "ok")
>    function f() (echo "also ok")
>
> function                                             old     new   delta
> parse_command                                       1555    1744    +189
> tokname_array                                        232     240      +8
> .rodata                                           155612  155566     -46
> ------------------------------------------------------------------------------
> (add/remove: 0/0 grow/shrink: 2/1 up/down: 197/-46)           Total: 151 bytes
>
> Signed-off-by: Ron Yorston <rmy@pobox.com>
> ---
>  shell/ash.c                              | 103 +++++++++++++++++++++----------
>  shell/ash_test/ash-misc/func_bash1.right |  12 ++++
>  shell/ash_test/ash-misc/func_bash1.tests |  28 +++++++++
>  3 files changed, 112 insertions(+), 31 deletions(-)
>  create mode 100644 shell/ash_test/ash-misc/func_bash1.right
>  create mode 100755 shell/ash_test/ash-misc/func_bash1.tests
>
> diff --git a/shell/ash.c b/shell/ash.c
> index 8450263..75d2839 100644
> --- a/shell/ash.c
> +++ b/shell/ash.c
> @@ -7726,36 +7726,40 @@ changepath(const char *new)
>         clearcmdentry(firstchange);
>         builtinloc = idx_bltin;
>  }
> -
> -#define TEOF 0
> -#define TNL 1
> -#define TREDIR 2
> -#define TWORD 3
> -#define TSEMI 4
> -#define TBACKGND 5
> -#define TAND 6
> -#define TOR 7
> -#define TPIPE 8
> -#define TLP 9
> -#define TRP 10
> -#define TENDCASE 11
> -#define TENDBQUOTE 12
> -#define TNOT 13
> -#define TCASE 14
> -#define TDO 15
> -#define TDONE 16
> -#define TELIF 17
> -#define TELSE 18
> -#define TESAC 19
> -#define TFI 20
> -#define TFOR 21
> -#define TIF 22
> -#define TIN 23
> -#define TTHEN 24
> -#define TUNTIL 25
> -#define TWHILE 26
> -#define TBEGIN 27
> -#define TEND 28
> +enum {
> +       TEOF,
> +       TNL,
> +       TREDIR,
> +       TWORD,
> +       TSEMI,
> +       TBACKGND,
> +       TAND,
> +       TOR,
> +       TPIPE,
> +       TLP,
> +       TRP,
> +       TENDCASE,
> +       TENDBQUOTE,
> +       TNOT,
> +       TCASE,
> +       TDO,
> +       TDONE,
> +       TELIF,
> +       TELSE,
> +       TESAC,
> +       TFI,
> +       TFOR,
> +#if ENABLE_ASH_BASH_COMPAT
> +       TFUNCTION,
> +#endif
> +       TIF,
> +       TIN,
> +       TTHEN,
> +       TUNTIL,
> +       TWHILE,
> +       TBEGIN,
> +       TEND
> +};
>  typedef smallint token_id_t;
>
>  /* first char is indicating which tokens mark the end of a list */
> @@ -7784,6 +7788,9 @@ static const char *const tokname_array[] = {
>         "\1esac",
>         "\1fi",
>         "\0for",
> +#if ENABLE_ASH_BASH_COMPAT
> +       "\0function",
> +#endif
>         "\0if",
>         "\0in",
>         "\1then",
> @@ -10762,6 +10769,7 @@ simplecmd(void)
>         int savecheckkwd;
>  #if ENABLE_ASH_BASH_COMPAT
>         smallint double_brackets_flag = 0;
> +       smallint function_flag = 0;
>  #endif
>
>         args = NULL;
> @@ -10778,6 +10786,11 @@ simplecmd(void)
>                 t = readtoken();
>                 switch (t) {
>  #if ENABLE_ASH_BASH_COMPAT
> +               case TFUNCTION:
> +                       if (peektoken() != TWORD)
> +                               raise_error_unexpected_syntax(TWORD);
> +                       function_flag = 1;
> +                       break;
>                 case TAND: /* "&&" */
>                 case TOR: /* "||" */
>                         if (!double_brackets_flag) {
> @@ -10806,6 +10819,29 @@ simplecmd(void)
>                                 app = &n->narg.next;
>                                 savecheckkwd = 0;
>                         }
> +#if ENABLE_ASH_BASH_COMPAT
> +                       if (function_flag) {
> +                               checkkwd = CHKNL | CHKKWD;
> +                               switch (peektoken()) {
> +                               case TBEGIN:
> +                               case TIF:
> +                               case TCASE:
> +                               case TUNTIL:
> +                               case TWHILE:
> +                               case TFOR:
> +                                       goto do_func;
> +                               case TLP:
> +                                       function_flag = 0;
> +                                       break;
> +                               case TWORD:
> +                                       if (strcmp("[[", wordtext) == 0)
> +                                               goto do_func;
> +                                       /* fall through */
> +                               default:
> +                                       raise_error_unexpected_syntax(-1);
> +                               }
> +                       }
> +#endif
>                         break;
>                 case TREDIR:
>                         *rpp = n = redirnode;
> @@ -10813,6 +10849,7 @@ simplecmd(void)
>                         parsefname();   /* read name of redirection file */
>                         break;
>                 case TLP:
> + IF_ASH_BASH_COMPAT(do_func:)
>                         if (args && app == &args->narg.next
>                          && !vars && !redir
>                         ) {
> @@ -10820,7 +10857,7 @@ simplecmd(void)
>                                 const char *name;
>
>                                 /* We have a function */
> -                               if (readtoken() != TRP)
> +                               if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP)
>                                         raise_error_unexpected_syntax(TRP);
>                                 name = n->narg.text;
>                                 if (!goodname(name)
> @@ -10833,6 +10870,7 @@ simplecmd(void)
>                                 n->narg.next = parse_command();
>                                 return n;
>                         }
> +                       IF_ASH_BASH_COMPAT(function_flag = 0;)
>                         /* fall through */
>                 default:
>                         tokpushback = 1;
> @@ -11013,6 +11051,9 @@ parse_command(void)
>                 n1 = list(0);
>                 t = TEND;
>                 break;
> +#if ENABLE_ASH_BASH_COMPAT
> +       case TFUNCTION:
> +#endif
>         case TWORD:
>         case TREDIR:
>                 tokpushback = 1;
> diff --git a/shell/ash_test/ash-misc/func_bash1.right b/shell/ash_test/ash-misc/func_bash1.right
> new file mode 100644
> index 0000000..41bf882
> --- /dev/null
> +++ b/shell/ash_test/ash-misc/func_bash1.right
> @@ -0,0 +1,12 @@
> +1
> +2
> +3
> +1
> +2
> +3
> +1
> +2
> +3
> +1
> +2
> +3
> diff --git a/shell/ash_test/ash-misc/func_bash1.tests b/shell/ash_test/ash-misc/func_bash1.tests
> new file mode 100755
> index 0000000..2cc0970
> --- /dev/null
> +++ b/shell/ash_test/ash-misc/func_bash1.tests
> @@ -0,0 +1,28 @@
> +function f() { echo $1; }
> +f 1
> +
> +function f() ( echo $1; )
> +f 2
> +
> +function f() ( echo $1 )
> +f 3
> +
> +function f() for i in 1 2 3; do
> +       echo $i
> +done
> +f
> +
> +function f { echo $1; }
> +f 1
> +
> +# the next two don't work
> +#function f ( echo $1; )
> +f 2
> +
> +#function f ( echo $1 )
> +f 3
> +
> +function f for i in 1 2 3; do
> +       echo $i
> +done
> +f
> --
> 2.4.3
>
> _______________________________________________
> busybox mailing list
> busybox@busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic