diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-14 17:13:20 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-14 17:13:20 +0000 |
commit | f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43 (patch) | |
tree | 3389ceea2b3b8db090cad74507acfa1c061c6a75 /shell | |
parent | dd316dd283704b9adb588c3fb7cdec6ba5fbceb8 (diff) | |
download | busybox-w32-f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43.tar.gz busybox-w32-f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43.tar.bz2 busybox-w32-f8d01d3f66dc50e54dae3c1d0e9b249f71f1dd43.zip |
hush: fix a bug where we were requiring semicolon here: (cmd;)
also fix a bug where after error prompt is not shown.
function old new delta
parse_stream 1612 1638 +26
parse_and_run_stream 361 375 +14
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/0 up/down: 40/0) Total: 40 bytes
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 53 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/colon.tests | 3 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/while_in_subshell.right (renamed from shell/hush_test/hush-bugs/while_in_subshell.right) | 0 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/while_in_subshell.tests (renamed from shell/hush_test/hush-bugs/while_in_subshell.tests) | 0 |
4 files changed, 34 insertions, 22 deletions
diff --git a/shell/hush.c b/shell/hush.c index a84bb92dc..f4c170117 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -3437,11 +3437,11 @@ static int parse_group(o_string *dest, struct p_context *ctx, | |||
3437 | child->subshell = 1; | 3437 | child->subshell = 1; |
3438 | } | 3438 | } |
3439 | rcode = parse_stream(dest, &sub, input, endch); | 3439 | rcode = parse_stream(dest, &sub, input, endch); |
3440 | //vda: err chk? | 3440 | if (rcode == 0) { |
3441 | done_word(dest, &sub); /* finish off the final word in the subcontext */ | 3441 | done_word(dest, &sub); /* finish off the final word in the subcontext */ |
3442 | done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ | 3442 | done_pipe(&sub, PIPE_SEQ); /* and the final command there, too */ |
3443 | child->group = sub.list_head; | 3443 | child->group = sub.list_head; |
3444 | 3444 | } | |
3445 | debug_printf_parse("parse_group return %d\n", rcode); | 3445 | debug_printf_parse("parse_group return %d\n", rcode); |
3446 | return rcode; | 3446 | return rcode; |
3447 | /* child remains "open", available for possible redirects */ | 3447 | /* child remains "open", available for possible redirects */ |
@@ -3700,11 +3700,19 @@ static int parse_stream(o_string *dest, struct p_context *ctx, | |||
3700 | done_pipe(ctx, PIPE_SEQ); | 3700 | done_pipe(ctx, PIPE_SEQ); |
3701 | } | 3701 | } |
3702 | } | 3702 | } |
3703 | if ((end_trigger && strchr(end_trigger, ch)) | 3703 | if (end_trigger) { |
3704 | && !dest->o_quote && ctx->res_w == RES_NONE | 3704 | if (!dest->o_quote && strchr(end_trigger, ch)) { |
3705 | ) { | 3705 | /* Special case: (...word) makes last word terminate, |
3706 | debug_printf_parse("parse_stream return 0: end_trigger char found\n"); | 3706 | * as if ';' is seen */ |
3707 | return 0; | 3707 | if (ch == ')') { |
3708 | done_word(dest, ctx); | ||
3709 | done_pipe(ctx, PIPE_SEQ); | ||
3710 | } | ||
3711 | if (ctx->res_w == RES_NONE) { | ||
3712 | debug_printf_parse("parse_stream return 0: end_trigger char found\n"); | ||
3713 | return 0; | ||
3714 | } | ||
3715 | } | ||
3708 | } | 3716 | } |
3709 | if (m == CHAR_IFS) | 3717 | if (m == CHAR_IFS) |
3710 | continue; | 3718 | continue; |
@@ -3757,15 +3765,15 @@ static int parse_stream(o_string *dest, struct p_context *ctx, | |||
3757 | dest->nonnull = 1; | 3765 | dest->nonnull = 1; |
3758 | while (1) { | 3766 | while (1) { |
3759 | ch = i_getch(input); | 3767 | ch = i_getch(input); |
3760 | if (ch == EOF || ch == '\'') | 3768 | if (ch == EOF) { |
3769 | syntax("unterminated '"); | ||
3770 | debug_printf_parse("parse_stream return 1: unterminated '\n"); | ||
3771 | return 1; | ||
3772 | } | ||
3773 | if (ch == '\'') | ||
3761 | break; | 3774 | break; |
3762 | o_addqchr(dest, ch); | 3775 | o_addqchr(dest, ch); |
3763 | } | 3776 | } |
3764 | if (ch == EOF) { | ||
3765 | syntax("unterminated '"); | ||
3766 | debug_printf_parse("parse_stream return 1: unterminated '\n"); | ||
3767 | return 1; | ||
3768 | } | ||
3769 | break; | 3777 | break; |
3770 | case '"': | 3778 | case '"': |
3771 | dest->nonnull = 1; | 3779 | dest->nonnull = 1; |
@@ -3861,7 +3869,7 @@ static int parse_stream(o_string *dest, struct p_context *ctx, | |||
3861 | if (ENABLE_HUSH_DEBUG) | 3869 | if (ENABLE_HUSH_DEBUG) |
3862 | bb_error_msg_and_die("BUG: unexpected %c\n", ch); | 3870 | bb_error_msg_and_die("BUG: unexpected %c\n", ch); |
3863 | } | 3871 | } |
3864 | } | 3872 | } /* while (1) */ |
3865 | /* Complain if quote? No, maybe we just finished a command substitution | 3873 | /* Complain if quote? No, maybe we just finished a command substitution |
3866 | * that was quoted. Example: | 3874 | * that was quoted. Example: |
3867 | * $ echo "`cat foo` plus more" | 3875 | * $ echo "`cat foo` plus more" |
@@ -3913,8 +3921,9 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) | |||
3913 | struct p_context ctx; | 3921 | struct p_context ctx; |
3914 | o_string temp = NULL_O_STRING; | 3922 | o_string temp = NULL_O_STRING; |
3915 | int rcode; | 3923 | int rcode; |
3924 | |||
3916 | do { | 3925 | do { |
3917 | // It always has PARSEFLAG_SEMICOLON, can we remove all checks for this bit? | 3926 | // parse_type always has PARSEFLAG_SEMICOLON, can we remove all checks for this bit? |
3918 | // After that, the whole parse_type fiels is not needed. | 3927 | // After that, the whole parse_type fiels is not needed. |
3919 | ctx.parse_type = parse_flag; | 3928 | ctx.parse_type = parse_flag; |
3920 | initialize_context(&ctx); | 3929 | initialize_context(&ctx); |
@@ -3938,17 +3947,21 @@ static int parse_and_run_stream(struct in_str *inp, int parse_flag) | |||
3938 | debug_printf_exec("parse_stream_outer: run_and_free_list\n"); | 3947 | debug_printf_exec("parse_stream_outer: run_and_free_list\n"); |
3939 | run_and_free_list(ctx.list_head); | 3948 | run_and_free_list(ctx.list_head); |
3940 | } else { | 3949 | } else { |
3950 | /* We arrive here also if rcode == 1 (error in parse_stream) */ | ||
3941 | if (ctx.old_flag != 0) { | 3951 | if (ctx.old_flag != 0) { |
3942 | free(ctx.stack); | 3952 | free(ctx.stack); |
3943 | o_reset(&temp); | 3953 | o_reset(&temp); |
3944 | } | 3954 | } |
3945 | temp.nonnull = 0; | 3955 | temp.nonnull = 0; |
3946 | temp.o_quote = 0; | 3956 | temp.o_quote = 0; |
3947 | inp->p = NULL; | ||
3948 | free_pipe_list(ctx.list_head, /* indent: */ 0); | 3957 | free_pipe_list(ctx.list_head, /* indent: */ 0); |
3958 | /* Discard all unprocessed line input, force prompt on */ | ||
3959 | inp->p = NULL; | ||
3960 | inp->promptme = 1; | ||
3949 | } | 3961 | } |
3950 | o_free(&temp); | 3962 | o_free(&temp); |
3951 | } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */ | 3963 | /* loop on syntax errors, return on EOF: */ |
3964 | } while (rcode != -1 && !(parse_flag & PARSEFLAG_EXIT_FROM_LOOP)); | ||
3952 | return 0; | 3965 | return 0; |
3953 | } | 3966 | } |
3954 | 3967 | ||
diff --git a/shell/hush_test/hush-misc/colon.tests b/shell/hush_test/hush-misc/colon.tests index ea3b4d5f3..cb8ab5306 100755 --- a/shell/hush_test/hush-misc/colon.tests +++ b/shell/hush_test/hush-misc/colon.tests | |||
@@ -1,6 +1,5 @@ | |||
1 | false | 1 | false |
2 | : | 2 | : |
3 | echo $? | 3 | echo $? |
4 | # Extra ; after done is due to a bug | 4 | (while :; do exit; done) |
5 | (while :; do exit; done;) | ||
6 | echo OK: $? | 5 | echo OK: $? |
diff --git a/shell/hush_test/hush-bugs/while_in_subshell.right b/shell/hush_test/hush-misc/while_in_subshell.right index 290d39b7e..290d39b7e 100644 --- a/shell/hush_test/hush-bugs/while_in_subshell.right +++ b/shell/hush_test/hush-misc/while_in_subshell.right | |||
diff --git a/shell/hush_test/hush-bugs/while_in_subshell.tests b/shell/hush_test/hush-misc/while_in_subshell.tests index def8e092b..def8e092b 100755 --- a/shell/hush_test/hush-bugs/while_in_subshell.tests +++ b/shell/hush_test/hush-misc/while_in_subshell.tests | |||