diff options
author | Denys Vlasenko | 2018-04-03 14:56:52 +0200 |
---|---|---|
committer | Denys Vlasenko | 2018-04-03 14:56:52 +0200 |
commit | fbf44854a3b7a32a0a0ff1a03f4163d25f2d62af (patch) | |
tree | b3963985e0dbaab4ef100a3c214cdf664dcc4aa9 /shell/hush.c | |
parent | 49015a60cb334ecd0b069f27833a3d50853509fa (diff) | |
download | busybox-fbf44854a3b7a32a0a0ff1a03f4163d25f2d62af.zip busybox-fbf44854a3b7a32a0a0ff1a03f4163d25f2d62af.tar.gz |
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.c | 79 |
1 files changed, 50 insertions, 29 deletions
diff --git a/shell/hush.c b/shell/hush.c index 94e429c..3351072 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -4297,6 +4297,11 @@ static int parse_group(o_string *dest, struct parse_context *ctx, /* dest contains characters seen prior to ( or {. * Typically it's empty, but for function defs, * it contains function name (without '()'). */ +#if BB_MMU +# define as_string NULL +#else + char *as_string = NULL; +#endif struct pipe *pipe_list; int endch; struct command *command = ctx->command; @@ -4325,7 +4330,7 @@ static int parse_group(o_string *dest, struct parse_context *ctx, do ch = i_getch(input); while (ch == ' ' || ch == '\t' || ch == '\n'); - if (ch != '{') { + if (ch != '{' && ch != '(') { syntax_error_unexpected_ch(ch); return 1; } @@ -4347,13 +4352,13 @@ static int parse_group(o_string *dest, struct parse_context *ctx, } #endif -#if ENABLE_HUSH_FUNCTIONS - skip: -#endif + IF_HUSH_FUNCTIONS(skip:) + endch = '}'; if (ch == '(') { endch = ')'; - command->cmd_type = CMD_SUBSHELL; + IF_HUSH_FUNCTIONS(if (command->cmd_type != CMD_FUNCDEF)) + command->cmd_type = CMD_SUBSHELL; } else { /* bash does not allow "{echo...", requires whitespace */ ch = i_peek(input); @@ -4369,38 +4374,54 @@ static int parse_group(o_string *dest, struct parse_context *ctx, } } - { -#if BB_MMU -# define as_string NULL -#else - char *as_string = NULL; -#endif - pipe_list = parse_stream(&as_string, input, endch); + pipe_list = parse_stream(&as_string, input, endch); #if !BB_MMU - if (as_string) - o_addstr(&ctx->as_string, as_string); + if (as_string) + o_addstr(&ctx->as_string, as_string); #endif - /* empty ()/{} or parse error? */ - if (!pipe_list || pipe_list == ERR_PTR) { - /* parse_stream already emitted error msg */ - if (!BB_MMU) - free(as_string); - debug_printf_parse("parse_group return 1: " - "parse_stream returned %p\n", pipe_list); - return 1; - } - command->group = pipe_list; + + /* empty ()/{} or parse error? */ + if (!pipe_list || pipe_list == ERR_PTR) { + /* parse_stream already emitted error msg */ + if (!BB_MMU) + free(as_string); + debug_printf_parse("parse_group return 1: " + "parse_stream returned %p\n", pipe_list); + return 1; + } #if !BB_MMU - as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */ - command->group_as_string = as_string; - debug_printf_parse("end of group, remembering as:'%s'\n", - command->group_as_string); + as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */ + command->group_as_string = as_string; + debug_printf_parse("end of group, remembering as:'%s'\n", + command->group_as_string); #endif -#undef as_string + +#if ENABLE_HUSH_FUNCTIONS + /* Convert "f() (cmds)" to "f() {(cmds)}" */ + if (command->cmd_type == CMD_FUNCDEF && endch == ')') { + struct command *cmd2; + + cmd2 = xzalloc(sizeof(*cmd2)); + cmd2->cmd_type = CMD_SUBSHELL; + cmd2->group = pipe_list; +# if !BB_MMU +//UNTESTED! + cmd2->group_as_string = command->group_as_string; + command->group_as_string = xasprintf("(%s)", command->group_as_string); +# endif + + pipe_list = new_pipe(); + pipe_list->cmds = cmd2; + pipe_list->num_cmds = 1; } +#endif + + command->group = pipe_list; + debug_printf_parse("parse_group return 0\n"); return 0; /* command remains "open", available for possible redirects */ +#undef as_string } #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS |