diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-03 14:56:52 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-03 14:56:52 +0200 |
commit | fbf44854a3b7a32a0a0ff1a03f4163d25f2d62af (patch) | |
tree | b3963985e0dbaab4ef100a3c214cdf664dcc4aa9 | |
parent | 49015a60cb334ecd0b069f27833a3d50853509fa (diff) | |
download | busybox-w32-fbf44854a3b7a32a0a0ff1a03f4163d25f2d62af.tar.gz busybox-w32-fbf44854a3b7a32a0a0ff1a03f4163d25f2d62af.tar.bz2 busybox-w32-fbf44854a3b7a32a0a0ff1a03f4163d25f2d62af.zip |
hush: support "f() (cmd)" functions
Many other shells support this construct
function old new delta
parse_stream 2950 3018 +68
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/ash_test/ash-misc/func5.right | 3 | ||||
-rwxr-xr-x | shell/ash_test/ash-misc/func5.tests | 5 | ||||
-rw-r--r-- | shell/ash_test/ash-misc/func_compound1.right | 3 | ||||
-rwxr-xr-x | shell/ash_test/ash-misc/func_compound1.tests | 4 | ||||
-rw-r--r-- | shell/hush.c | 79 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/func5.tests | 5 |
6 files changed, 59 insertions, 40 deletions
diff --git a/shell/ash_test/ash-misc/func5.right b/shell/ash_test/ash-misc/func5.right index 2c9d316b3..01e79c32a 100644 --- a/shell/ash_test/ash-misc/func5.right +++ b/shell/ash_test/ash-misc/func5.right | |||
@@ -1,6 +1,3 @@ | |||
1 | 1 | 1 | 1 |
2 | 2 | 2 | 2 |
3 | 3 | 3 | 3 |
4 | 1 | ||
5 | 2 | ||
6 | 3 | ||
diff --git a/shell/ash_test/ash-misc/func5.tests b/shell/ash_test/ash-misc/func5.tests index e967208cc..5c33560bc 100755 --- a/shell/ash_test/ash-misc/func5.tests +++ b/shell/ash_test/ash-misc/func5.tests | |||
@@ -6,8 +6,3 @@ f 2 | |||
6 | 6 | ||
7 | f() ( echo $1 ) | 7 | f() ( echo $1 ) |
8 | f 3 | 8 | f 3 |
9 | |||
10 | f() for i in 1 2 3; do | ||
11 | echo $i | ||
12 | done | ||
13 | f | ||
diff --git a/shell/ash_test/ash-misc/func_compound1.right b/shell/ash_test/ash-misc/func_compound1.right new file mode 100644 index 000000000..01e79c32a --- /dev/null +++ b/shell/ash_test/ash-misc/func_compound1.right | |||
@@ -0,0 +1,3 @@ | |||
1 | 1 | ||
2 | 2 | ||
3 | 3 | ||
diff --git a/shell/ash_test/ash-misc/func_compound1.tests b/shell/ash_test/ash-misc/func_compound1.tests new file mode 100755 index 000000000..20c8bf18b --- /dev/null +++ b/shell/ash_test/ash-misc/func_compound1.tests | |||
@@ -0,0 +1,4 @@ | |||
1 | f() for i in 1 2 3; do | ||
2 | echo $i | ||
3 | done | ||
4 | f | ||
diff --git a/shell/hush.c b/shell/hush.c index 94e429c0d..335107283 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -4297,6 +4297,11 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
4297 | /* dest contains characters seen prior to ( or {. | 4297 | /* dest contains characters seen prior to ( or {. |
4298 | * Typically it's empty, but for function defs, | 4298 | * Typically it's empty, but for function defs, |
4299 | * it contains function name (without '()'). */ | 4299 | * it contains function name (without '()'). */ |
4300 | #if BB_MMU | ||
4301 | # define as_string NULL | ||
4302 | #else | ||
4303 | char *as_string = NULL; | ||
4304 | #endif | ||
4300 | struct pipe *pipe_list; | 4305 | struct pipe *pipe_list; |
4301 | int endch; | 4306 | int endch; |
4302 | struct command *command = ctx->command; | 4307 | struct command *command = ctx->command; |
@@ -4325,7 +4330,7 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
4325 | do | 4330 | do |
4326 | ch = i_getch(input); | 4331 | ch = i_getch(input); |
4327 | while (ch == ' ' || ch == '\t' || ch == '\n'); | 4332 | while (ch == ' ' || ch == '\t' || ch == '\n'); |
4328 | if (ch != '{') { | 4333 | if (ch != '{' && ch != '(') { |
4329 | syntax_error_unexpected_ch(ch); | 4334 | syntax_error_unexpected_ch(ch); |
4330 | return 1; | 4335 | return 1; |
4331 | } | 4336 | } |
@@ -4347,13 +4352,13 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
4347 | } | 4352 | } |
4348 | #endif | 4353 | #endif |
4349 | 4354 | ||
4350 | #if ENABLE_HUSH_FUNCTIONS | 4355 | IF_HUSH_FUNCTIONS(skip:) |
4351 | skip: | 4356 | |
4352 | #endif | ||
4353 | endch = '}'; | 4357 | endch = '}'; |
4354 | if (ch == '(') { | 4358 | if (ch == '(') { |
4355 | endch = ')'; | 4359 | endch = ')'; |
4356 | command->cmd_type = CMD_SUBSHELL; | 4360 | IF_HUSH_FUNCTIONS(if (command->cmd_type != CMD_FUNCDEF)) |
4361 | command->cmd_type = CMD_SUBSHELL; | ||
4357 | } else { | 4362 | } else { |
4358 | /* bash does not allow "{echo...", requires whitespace */ | 4363 | /* bash does not allow "{echo...", requires whitespace */ |
4359 | ch = i_peek(input); | 4364 | ch = i_peek(input); |
@@ -4369,38 +4374,54 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
4369 | } | 4374 | } |
4370 | } | 4375 | } |
4371 | 4376 | ||
4372 | { | 4377 | pipe_list = parse_stream(&as_string, input, endch); |
4373 | #if BB_MMU | ||
4374 | # define as_string NULL | ||
4375 | #else | ||
4376 | char *as_string = NULL; | ||
4377 | #endif | ||
4378 | pipe_list = parse_stream(&as_string, input, endch); | ||
4379 | #if !BB_MMU | 4378 | #if !BB_MMU |
4380 | if (as_string) | 4379 | if (as_string) |
4381 | o_addstr(&ctx->as_string, as_string); | 4380 | o_addstr(&ctx->as_string, as_string); |
4382 | #endif | 4381 | #endif |
4383 | /* empty ()/{} or parse error? */ | 4382 | |
4384 | if (!pipe_list || pipe_list == ERR_PTR) { | 4383 | /* empty ()/{} or parse error? */ |
4385 | /* parse_stream already emitted error msg */ | 4384 | if (!pipe_list || pipe_list == ERR_PTR) { |
4386 | if (!BB_MMU) | 4385 | /* parse_stream already emitted error msg */ |
4387 | free(as_string); | 4386 | if (!BB_MMU) |
4388 | debug_printf_parse("parse_group return 1: " | 4387 | free(as_string); |
4389 | "parse_stream returned %p\n", pipe_list); | 4388 | debug_printf_parse("parse_group return 1: " |
4390 | return 1; | 4389 | "parse_stream returned %p\n", pipe_list); |
4391 | } | 4390 | return 1; |
4392 | command->group = pipe_list; | 4391 | } |
4393 | #if !BB_MMU | 4392 | #if !BB_MMU |
4394 | as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */ | 4393 | as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */ |
4395 | command->group_as_string = as_string; | 4394 | command->group_as_string = as_string; |
4396 | debug_printf_parse("end of group, remembering as:'%s'\n", | 4395 | debug_printf_parse("end of group, remembering as:'%s'\n", |
4397 | command->group_as_string); | 4396 | command->group_as_string); |
4398 | #endif | 4397 | #endif |
4399 | #undef as_string | 4398 | |
4399 | #if ENABLE_HUSH_FUNCTIONS | ||
4400 | /* Convert "f() (cmds)" to "f() {(cmds)}" */ | ||
4401 | if (command->cmd_type == CMD_FUNCDEF && endch == ')') { | ||
4402 | struct command *cmd2; | ||
4403 | |||
4404 | cmd2 = xzalloc(sizeof(*cmd2)); | ||
4405 | cmd2->cmd_type = CMD_SUBSHELL; | ||
4406 | cmd2->group = pipe_list; | ||
4407 | # if !BB_MMU | ||
4408 | //UNTESTED! | ||
4409 | cmd2->group_as_string = command->group_as_string; | ||
4410 | command->group_as_string = xasprintf("(%s)", command->group_as_string); | ||
4411 | # endif | ||
4412 | |||
4413 | pipe_list = new_pipe(); | ||
4414 | pipe_list->cmds = cmd2; | ||
4415 | pipe_list->num_cmds = 1; | ||
4400 | } | 4416 | } |
4417 | #endif | ||
4418 | |||
4419 | command->group = pipe_list; | ||
4420 | |||
4401 | debug_printf_parse("parse_group return 0\n"); | 4421 | debug_printf_parse("parse_group return 0\n"); |
4402 | return 0; | 4422 | return 0; |
4403 | /* command remains "open", available for possible redirects */ | 4423 | /* command remains "open", available for possible redirects */ |
4424 | #undef as_string | ||
4404 | } | 4425 | } |
4405 | 4426 | ||
4406 | #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS | 4427 | #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS |
diff --git a/shell/hush_test/hush-misc/func5.tests b/shell/hush_test/hush-misc/func5.tests index 9c5f9fa48..5c33560bc 100755 --- a/shell/hush_test/hush-misc/func5.tests +++ b/shell/hush_test/hush-misc/func5.tests | |||
@@ -1,9 +1,8 @@ | |||
1 | f() { echo $1; } | 1 | f() { echo $1; } |
2 | f 1 | 2 | f 1 |
3 | 3 | ||
4 | # hush fails on this syntax, but i've never seen anyone use it ... | 4 | f() ( echo $1; ) |
5 | #f() ( echo $1; ) | ||
6 | f 2 | 5 | f 2 |
7 | 6 | ||
8 | #f() ( echo $1 ) | 7 | f() ( echo $1 ) |
9 | f 3 | 8 | f 3 |