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>
This commit is contained in:
parent
49015a60cb
commit
fbf44854a3
@ -1,6 +1,3 @@
|
|||||||
1
|
1
|
||||||
2
|
2
|
||||||
3
|
3
|
||||||
1
|
|
||||||
2
|
|
||||||
3
|
|
||||||
|
@ -6,8 +6,3 @@ f 2
|
|||||||
|
|
||||||
f() ( echo $1 )
|
f() ( echo $1 )
|
||||||
f 3
|
f 3
|
||||||
|
|
||||||
f() for i in 1 2 3; do
|
|
||||||
echo $i
|
|
||||||
done
|
|
||||||
f
|
|
||||||
|
3
shell/ash_test/ash-misc/func_compound1.right
Normal file
3
shell/ash_test/ash-misc/func_compound1.right
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
4
shell/ash_test/ash-misc/func_compound1.tests
Executable file
4
shell/ash_test/ash-misc/func_compound1.tests
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
f() for i in 1 2 3; do
|
||||||
|
echo $i
|
||||||
|
done
|
||||||
|
f
|
45
shell/hush.c
45
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 {.
|
/* dest contains characters seen prior to ( or {.
|
||||||
* Typically it's empty, but for function defs,
|
* Typically it's empty, but for function defs,
|
||||||
* it contains function name (without '()'). */
|
* it contains function name (without '()'). */
|
||||||
|
#if BB_MMU
|
||||||
|
# define as_string NULL
|
||||||
|
#else
|
||||||
|
char *as_string = NULL;
|
||||||
|
#endif
|
||||||
struct pipe *pipe_list;
|
struct pipe *pipe_list;
|
||||||
int endch;
|
int endch;
|
||||||
struct command *command = ctx->command;
|
struct command *command = ctx->command;
|
||||||
@ -4325,7 +4330,7 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
|
|||||||
do
|
do
|
||||||
ch = i_getch(input);
|
ch = i_getch(input);
|
||||||
while (ch == ' ' || ch == '\t' || ch == '\n');
|
while (ch == ' ' || ch == '\t' || ch == '\n');
|
||||||
if (ch != '{') {
|
if (ch != '{' && ch != '(') {
|
||||||
syntax_error_unexpected_ch(ch);
|
syntax_error_unexpected_ch(ch);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -4347,12 +4352,12 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ENABLE_HUSH_FUNCTIONS
|
IF_HUSH_FUNCTIONS(skip:)
|
||||||
skip:
|
|
||||||
#endif
|
|
||||||
endch = '}';
|
endch = '}';
|
||||||
if (ch == '(') {
|
if (ch == '(') {
|
||||||
endch = ')';
|
endch = ')';
|
||||||
|
IF_HUSH_FUNCTIONS(if (command->cmd_type != CMD_FUNCDEF))
|
||||||
command->cmd_type = CMD_SUBSHELL;
|
command->cmd_type = CMD_SUBSHELL;
|
||||||
} else {
|
} else {
|
||||||
/* bash does not allow "{echo...", requires whitespace */
|
/* bash does not allow "{echo...", requires whitespace */
|
||||||
@ -4369,17 +4374,12 @@ 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 !BB_MMU
|
||||||
if (as_string)
|
if (as_string)
|
||||||
o_addstr(&ctx->as_string, as_string);
|
o_addstr(&ctx->as_string, as_string);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* empty ()/{} or parse error? */
|
/* empty ()/{} or parse error? */
|
||||||
if (!pipe_list || pipe_list == ERR_PTR) {
|
if (!pipe_list || pipe_list == ERR_PTR) {
|
||||||
/* parse_stream already emitted error msg */
|
/* parse_stream already emitted error msg */
|
||||||
@ -4389,18 +4389,39 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
|
|||||||
"parse_stream returned %p\n", pipe_list);
|
"parse_stream returned %p\n", pipe_list);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
command->group = pipe_list;
|
|
||||||
#if !BB_MMU
|
#if !BB_MMU
|
||||||
as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
|
as_string[strlen(as_string) - 1] = '\0'; /* plink ')' or '}' */
|
||||||
command->group_as_string = as_string;
|
command->group_as_string = as_string;
|
||||||
debug_printf_parse("end of group, remembering as:'%s'\n",
|
debug_printf_parse("end of group, remembering as:'%s'\n",
|
||||||
command->group_as_string);
|
command->group_as_string);
|
||||||
#endif
|
#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");
|
debug_printf_parse("parse_group return 0\n");
|
||||||
return 0;
|
return 0;
|
||||||
/* command remains "open", available for possible redirects */
|
/* command remains "open", available for possible redirects */
|
||||||
|
#undef as_string
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
|
#if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
f() { echo $1; }
|
f() { echo $1; }
|
||||||
f 1
|
f 1
|
||||||
|
|
||||||
# hush fails on this syntax, but i've never seen anyone use it ...
|
f() ( echo $1; )
|
||||||
#f() ( echo $1; )
|
|
||||||
f 2
|
f 2
|
||||||
|
|
||||||
#f() ( echo $1 )
|
f() ( echo $1 )
|
||||||
f 3
|
f 3
|
||||||
|
Loading…
Reference in New Issue
Block a user