aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-04-03 14:56:52 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-04-03 14:56:52 +0200
commitfbf44854a3b7a32a0a0ff1a03f4163d25f2d62af (patch)
treeb3963985e0dbaab4ef100a3c214cdf664dcc4aa9
parent49015a60cb334ecd0b069f27833a3d50853509fa (diff)
downloadbusybox-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.right3
-rwxr-xr-xshell/ash_test/ash-misc/func5.tests5
-rw-r--r--shell/ash_test/ash-misc/func_compound1.right3
-rwxr-xr-xshell/ash_test/ash-misc/func_compound1.tests4
-rw-r--r--shell/hush.c79
-rwxr-xr-xshell/hush_test/hush-misc/func5.tests5
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 @@
11 11
22 22
33 33
41
52
63
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
7f() ( echo $1 ) 7f() ( echo $1 )
8f 3 8f 3
9
10f() for i in 1 2 3; do
11 echo $i
12done
13f
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 @@
11
22
33
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 @@
1f() for i in 1 2 3; do
2 echo $i
3done
4f
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 @@
1f() { echo $1; } 1f() { echo $1; }
2f 1 2f 1
3 3
4# hush fails on this syntax, but i've never seen anyone use it ... 4f() ( echo $1; )
5#f() ( echo $1; )
6f 2 5f 2
7 6
8#f() ( echo $1 ) 7f() ( echo $1 )
9f 3 8f 3