aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
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 /shell/hush.c
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>
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c79
1 files changed, 50 insertions, 29 deletions
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