From 85405c80a28509f2f36c0d4fda8693aac7652d9b Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 3 Nov 2015 09:37:40 +0000 Subject: ash: copy function tests from hush testsuite Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/func1.right | 6 ++++++ shell/ash_test/ash-misc/func1.tests | 16 ++++++++++++++++ shell/ash_test/ash-misc/func2.right | 5 +++++ shell/ash_test/ash-misc/func2.tests | 9 +++++++++ shell/ash_test/ash-misc/func3.right | 4 ++++ shell/ash_test/ash-misc/func3.tests | 8 ++++++++ shell/ash_test/ash-misc/func4.right | 2 ++ shell/ash_test/ash-misc/func4.tests | 7 +++++++ shell/ash_test/ash-misc/func5.right | 6 ++++++ shell/ash_test/ash-misc/func5.tests | 13 +++++++++++++ shell/ash_test/ash-misc/func_args1.right | 5 +++++ shell/ash_test/ash-misc/func_args1.tests | 9 +++++++++ shell/ash_test/ash-misc/func_local1.right | 3 +++ shell/ash_test/ash-misc/func_local1.tests | 5 +++++ shell/ash_test/ash-misc/func_local2.right | 14 ++++++++++++++ shell/ash_test/ash-misc/func_local2.tests | 7 +++++++ 16 files changed, 119 insertions(+) create mode 100644 shell/ash_test/ash-misc/func1.right create mode 100755 shell/ash_test/ash-misc/func1.tests create mode 100644 shell/ash_test/ash-misc/func2.right create mode 100755 shell/ash_test/ash-misc/func2.tests create mode 100644 shell/ash_test/ash-misc/func3.right create mode 100755 shell/ash_test/ash-misc/func3.tests create mode 100644 shell/ash_test/ash-misc/func4.right create mode 100755 shell/ash_test/ash-misc/func4.tests create mode 100644 shell/ash_test/ash-misc/func5.right create mode 100755 shell/ash_test/ash-misc/func5.tests create mode 100644 shell/ash_test/ash-misc/func_args1.right create mode 100755 shell/ash_test/ash-misc/func_args1.tests create mode 100644 shell/ash_test/ash-misc/func_local1.right create mode 100755 shell/ash_test/ash-misc/func_local1.tests create mode 100644 shell/ash_test/ash-misc/func_local2.right create mode 100755 shell/ash_test/ash-misc/func_local2.tests (limited to 'shell') diff --git a/shell/ash_test/ash-misc/func1.right b/shell/ash_test/ash-misc/func1.right new file mode 100644 index 000000000..e21665aaf --- /dev/null +++ b/shell/ash_test/ash-misc/func1.right @@ -0,0 +1,6 @@ +Hello +Zero: 0 +One: 1 Param1: World +Zero: 0 Param1: Restored +Multi line function +One: 1 diff --git a/shell/ash_test/ash-misc/func1.tests b/shell/ash_test/ash-misc/func1.tests new file mode 100755 index 000000000..ffb269fad --- /dev/null +++ b/shell/ash_test/ash-misc/func1.tests @@ -0,0 +1,16 @@ +f() { echo Hello; } +g () { echo One: $# Param1: $1; } +h ( ) +{ + echo -n 'Multi ' && echo -n 'line ' + echo function + false +} + +f +echo Zero: $? +set -- Restored +{ g World; } +echo Zero: $? Param1: $1 +( h ) +echo One: $? diff --git a/shell/ash_test/ash-misc/func2.right b/shell/ash_test/ash-misc/func2.right new file mode 100644 index 000000000..f2a041da7 --- /dev/null +++ b/shell/ash_test/ash-misc/func2.right @@ -0,0 +1,5 @@ +First 0 +Second 0 +First 1 +Second 1 +Done diff --git a/shell/ash_test/ash-misc/func2.tests b/shell/ash_test/ash-misc/func2.tests new file mode 100755 index 000000000..763203f15 --- /dev/null +++ b/shell/ash_test/ash-misc/func2.tests @@ -0,0 +1,9 @@ +i=0 +while test $i != 2; do + f() { echo First $i; } + f + f() { echo Second $i; } + f + : $((i++)) +done +echo Done diff --git a/shell/ash_test/ash-misc/func3.right b/shell/ash_test/ash-misc/func3.right new file mode 100644 index 000000000..b6d73459a --- /dev/null +++ b/shell/ash_test/ash-misc/func3.right @@ -0,0 +1,4 @@ +One:1 +Zero:0 +One:1 +Five:5 diff --git a/shell/ash_test/ash-misc/func3.tests b/shell/ash_test/ash-misc/func3.tests new file mode 100755 index 000000000..fa6f26a23 --- /dev/null +++ b/shell/ash_test/ash-misc/func3.tests @@ -0,0 +1,8 @@ +f() { false; return; echo BAD; }; +{ f; echo One:$?; }; echo Zero:$? + +f() { false; return; }; +f; echo One:$? + +f() { return 5; }; +f; echo Five:$? diff --git a/shell/ash_test/ash-misc/func4.right b/shell/ash_test/ash-misc/func4.right new file mode 100644 index 000000000..0c87e316a --- /dev/null +++ b/shell/ash_test/ash-misc/func4.right @@ -0,0 +1,2 @@ +24 +Done diff --git a/shell/ash_test/ash-misc/func4.tests b/shell/ash_test/ash-misc/func4.tests new file mode 100755 index 000000000..74c1b9a46 --- /dev/null +++ b/shell/ash_test/ash-misc/func4.tests @@ -0,0 +1,7 @@ +func() { + eval "echo \"\${val_${1}}\"" +} + +val_x=24 +(func x) +echo Done diff --git a/shell/ash_test/ash-misc/func5.right b/shell/ash_test/ash-misc/func5.right new file mode 100644 index 000000000..2c9d316b3 --- /dev/null +++ b/shell/ash_test/ash-misc/func5.right @@ -0,0 +1,6 @@ +1 +2 +3 +1 +2 +3 diff --git a/shell/ash_test/ash-misc/func5.tests b/shell/ash_test/ash-misc/func5.tests new file mode 100755 index 000000000..e967208cc --- /dev/null +++ b/shell/ash_test/ash-misc/func5.tests @@ -0,0 +1,13 @@ +f() { echo $1; } +f 1 + +f() ( echo $1; ) +f 2 + +f() ( echo $1 ) +f 3 + +f() for i in 1 2 3; do + echo $i +done +f diff --git a/shell/ash_test/ash-misc/func_args1.right b/shell/ash_test/ash-misc/func_args1.right new file mode 100644 index 000000000..2dfb9629b --- /dev/null +++ b/shell/ash_test/ash-misc/func_args1.right @@ -0,0 +1,5 @@ +params: a b c +'f 1 2 3' called +params: a b c +'f 1 2 3' called +params: a b c diff --git a/shell/ash_test/ash-misc/func_args1.tests b/shell/ash_test/ash-misc/func_args1.tests new file mode 100755 index 000000000..7970795a9 --- /dev/null +++ b/shell/ash_test/ash-misc/func_args1.tests @@ -0,0 +1,9 @@ + +f() { echo "'f $1 $2 $3' called"; } + +set -- a b c +echo "params: $1 $2 $3" +f 1 2 3 +echo "params: $1 $2 $3" +true | f 1 2 3 +echo "params: $1 $2 $3" diff --git a/shell/ash_test/ash-misc/func_local1.right b/shell/ash_test/ash-misc/func_local1.right new file mode 100644 index 000000000..312178366 --- /dev/null +++ b/shell/ash_test/ash-misc/func_local1.right @@ -0,0 +1,3 @@ +z=a +z=z +Done diff --git a/shell/ash_test/ash-misc/func_local1.tests b/shell/ash_test/ash-misc/func_local1.tests new file mode 100755 index 000000000..1d594e20c --- /dev/null +++ b/shell/ash_test/ash-misc/func_local1.tests @@ -0,0 +1,5 @@ +export z=z +f() { local z=a; env | grep ^z; } +f +env | grep ^z +echo Done diff --git a/shell/ash_test/ash-misc/func_local2.right b/shell/ash_test/ash-misc/func_local2.right new file mode 100644 index 000000000..fe9343ac8 --- /dev/null +++ b/shell/ash_test/ash-misc/func_local2.right @@ -0,0 +1,14 @@ +1 +2 +1 +2 +1 +1 +2 +2 +3 +2 +2 +3 +1 +Done diff --git a/shell/ash_test/ash-misc/func_local2.tests b/shell/ash_test/ash-misc/func_local2.tests new file mode 100755 index 000000000..1a9ae559d --- /dev/null +++ b/shell/ash_test/ash-misc/func_local2.tests @@ -0,0 +1,7 @@ +x=1 +f() { echo $x; local x=$((x+1)); echo $x; } +g() { f; echo $x; f; local x=$((x+1)); f; echo $x; f; } +f +g +echo $x +echo Done -- cgit v1.2.3-55-g6feb From bc9bee01f35d6c716c087e82dae5f439de90914b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 4 Nov 2015 14:50:19 +0100 Subject: hush-misc/func_args1.tests: remove "UNFIXED BUG", it does not fail Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/func_args1.tests | 1 - shell/hush_test/hush-misc/func_args1.tests | 2 -- 2 files changed, 3 deletions(-) (limited to 'shell') diff --git a/shell/ash_test/ash-misc/func_args1.tests b/shell/ash_test/ash-misc/func_args1.tests index 7970795a9..d394c637f 100755 --- a/shell/ash_test/ash-misc/func_args1.tests +++ b/shell/ash_test/ash-misc/func_args1.tests @@ -1,4 +1,3 @@ - f() { echo "'f $1 $2 $3' called"; } set -- a b c diff --git a/shell/hush_test/hush-misc/func_args1.tests b/shell/hush_test/hush-misc/func_args1.tests index 157921fb1..d394c637f 100755 --- a/shell/hush_test/hush-misc/func_args1.tests +++ b/shell/hush_test/hush-misc/func_args1.tests @@ -1,5 +1,3 @@ -# UNFIXED BUG - f() { echo "'f $1 $2 $3' called"; } set -- a b c -- cgit v1.2.3-55-g6feb From 95ebcf79ff6f8ad21ceacb7bac665fb86c078d84 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 3 Nov 2015 09:42:23 +0000 Subject: ash: add support for bash 'function' keyword 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 Signed-off-by: Denys Vlasenko --- shell/ash.c | 101 +++++++++++++++++++++---------- shell/ash_test/ash-misc/func_bash1.right | 12 ++++ shell/ash_test/ash-misc/func_bash1.tests | 28 +++++++++ 3 files changed, 110 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 (limited to 'shell') diff --git a/shell/ash.c b/shell/ash.c index 84502636a..e7a867f52 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,7 @@ parse_command(void) n1 = list(0); t = TEND; break; + IF_ASH_BASH_COMPAT(case TFUNCTION:) 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 000000000..41bf8828c --- /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 000000000..2cc0970e8 --- /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 -- cgit v1.2.3-55-g6feb