diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-10 13:49:10 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2009-04-10 13:49:10 +0000 |
commit | 0b677d833718ab6c46bd4790c662c67fba4f377a (patch) | |
tree | d4a9cc818a546476c0617f93f5efc13a6a7d2a15 | |
parent | 1fd1ea4395e520694bd9f8b1dc9e60af6442946d (diff) | |
download | busybox-w32-0b677d833718ab6c46bd4790c662c67fba4f377a.tar.gz busybox-w32-0b677d833718ab6c46bd4790c662c67fba4f377a.tar.bz2 busybox-w32-0b677d833718ab6c46bd4790c662c67fba4f377a.zip |
hush: fix some TODOs. TODO in export builting: +250 bytes.
simplify unexpected EOF handling.
function old new delta
builtin_export 117 374 +257
o_reset_to_empty_unquoted - 21 +21
parse_stream 1926 1929 +3
syntax_error_unterm_ch 31 32 +1
handle_dollar 644 641 -3
parse_stream_dquoted 307 298 -9
add_till_backquote 106 97 -9
add_till_closing_paren 303 286 -17
o_reset 21 - -21
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 3/4 up/down: 282/-59) Total: 223 bytes
-rw-r--r-- | shell/hush.c | 127 | ||||
-rw-r--r-- | shell/hush_test/hush-misc/export.right | 6 | ||||
-rwxr-xr-x | shell/hush_test/hush-misc/export.tests | 7 |
3 files changed, 89 insertions, 51 deletions
diff --git a/shell/hush.c b/shell/hush.c index 422fc63f6..e3dfa0673 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -701,12 +701,19 @@ static void syntax_error_at(unsigned lineno, const char *msg) | |||
701 | die_if_script(lineno, "syntax error at '%s'", msg); | 701 | die_if_script(lineno, "syntax error at '%s'", msg); |
702 | } | 702 | } |
703 | 703 | ||
704 | /* It so happens that all such cases are totally fatal | ||
705 | * even if shell is interactive: EOF while looking for closing | ||
706 | * delimiter. There is nowhere to read stuff from after that, | ||
707 | * it's EOF! The only choice is to terminate. | ||
708 | */ | ||
709 | static void syntax_error_unterm_ch(unsigned lineno, char ch) NORETURN; | ||
704 | static void syntax_error_unterm_ch(unsigned lineno, char ch) | 710 | static void syntax_error_unterm_ch(unsigned lineno, char ch) |
705 | { | 711 | { |
706 | char msg[2]; | 712 | char msg[2]; |
707 | msg[0] = ch; | 713 | msg[0] = ch; |
708 | msg[1] = '\0'; | 714 | msg[1] = '\0'; |
709 | die_if_script(lineno, "syntax error: unterminated %s", msg); | 715 | die_if_script(lineno, "syntax error: unterminated %s", msg); |
716 | xfunc_die(); | ||
710 | } | 717 | } |
711 | 718 | ||
712 | static void syntax_error_unterm_str(unsigned lineno, const char *s) | 719 | static void syntax_error_unterm_str(unsigned lineno, const char *s) |
@@ -1433,7 +1440,7 @@ static void setup_string_in_str(struct in_str *i, const char *s) | |||
1433 | */ | 1440 | */ |
1434 | #define B_CHUNK (32 * sizeof(char*)) | 1441 | #define B_CHUNK (32 * sizeof(char*)) |
1435 | 1442 | ||
1436 | static void o_reset(o_string *o) | 1443 | static void o_reset_to_empty_unquoted(o_string *o) |
1437 | { | 1444 | { |
1438 | o->length = 0; | 1445 | o->length = 0; |
1439 | o->o_quoted = 0; | 1446 | o->o_quoted = 0; |
@@ -4043,7 +4050,7 @@ static int done_word(o_string *word, struct parse_context *ctx) | |||
4043 | ) { | 4050 | ) { |
4044 | debug_printf_parse(": checking '%s' for reserved-ness\n", word->data); | 4051 | debug_printf_parse(": checking '%s' for reserved-ness\n", word->data); |
4045 | if (reserved_word(word, ctx)) { | 4052 | if (reserved_word(word, ctx)) { |
4046 | o_reset(word); | 4053 | o_reset_to_empty_unquoted(word); |
4047 | debug_printf_parse("done_word return %d\n", | 4054 | debug_printf_parse("done_word return %d\n", |
4048 | (ctx->ctx_res_w == RES_SNTX)); | 4055 | (ctx->ctx_res_w == RES_SNTX)); |
4049 | return (ctx->ctx_res_w == RES_SNTX); | 4056 | return (ctx->ctx_res_w == RES_SNTX); |
@@ -4099,7 +4106,7 @@ static int done_word(o_string *word, struct parse_context *ctx) | |||
4099 | } | 4106 | } |
4100 | #endif | 4107 | #endif |
4101 | 4108 | ||
4102 | o_reset(word); | 4109 | o_reset_to_empty_unquoted(word); |
4103 | 4110 | ||
4104 | debug_printf_parse("done_word return 0\n"); | 4111 | debug_printf_parse("done_word return 0\n"); |
4105 | return 0; | 4112 | return 0; |
@@ -4249,7 +4256,7 @@ static int redirect_opt_num(o_string *o) | |||
4249 | num = bb_strtou(o->data, NULL, 10); | 4256 | num = bb_strtou(o->data, NULL, 10); |
4250 | if (errno || num < 0) | 4257 | if (errno || num < 0) |
4251 | return -1; | 4258 | return -1; |
4252 | o_reset(o); | 4259 | o_reset_to_empty_unquoted(o); |
4253 | return num; | 4260 | return num; |
4254 | } | 4261 | } |
4255 | 4262 | ||
@@ -4458,7 +4465,6 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
4458 | bb_error_msg("aha '%s' is a function, parsing it...", dest->data); | 4465 | bb_error_msg("aha '%s' is a function, parsing it...", dest->data); |
4459 | //command->fname = dest->data; | 4466 | //command->fname = dest->data; |
4460 | command->grp_type = GRP_FUNCTION; | 4467 | command->grp_type = GRP_FUNCTION; |
4461 | //TODO: review every o_reset() location... do they handle all o_string fields correctly? | ||
4462 | memset(dest, 0, sizeof(*dest)); | 4468 | memset(dest, 0, sizeof(*dest)); |
4463 | } | 4469 | } |
4464 | #endif | 4470 | #endif |
@@ -4510,40 +4516,39 @@ static int parse_group(o_string *dest, struct parse_context *ctx, | |||
4510 | 4516 | ||
4511 | #if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT | 4517 | #if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT |
4512 | /* Subroutines for copying $(...) and `...` things */ | 4518 | /* Subroutines for copying $(...) and `...` things */ |
4513 | static int add_till_backquote(o_string *dest, struct in_str *input); | 4519 | static void add_till_backquote(o_string *dest, struct in_str *input); |
4514 | /* '...' */ | 4520 | /* '...' */ |
4515 | static int add_till_single_quote(o_string *dest, struct in_str *input) | 4521 | static void add_till_single_quote(o_string *dest, struct in_str *input) |
4516 | { | 4522 | { |
4517 | while (1) { | 4523 | while (1) { |
4518 | int ch = i_getch(input); | 4524 | int ch = i_getch(input); |
4519 | if (ch == EOF) { | 4525 | if (ch == EOF) { |
4520 | syntax_error_unterm_ch('\''); | 4526 | syntax_error_unterm_ch('\''); |
4521 | return 1; | 4527 | /*xfunc_die(); - redundant */ |
4522 | } | 4528 | } |
4523 | if (ch == '\'') | 4529 | if (ch == '\'') |
4524 | return 0; | 4530 | return; |
4525 | o_addchr(dest, ch); | 4531 | o_addchr(dest, ch); |
4526 | } | 4532 | } |
4527 | } | 4533 | } |
4528 | /* "...\"...`..`...." - do we need to handle "...$(..)..." too? */ | 4534 | /* "...\"...`..`...." - do we need to handle "...$(..)..." too? */ |
4529 | static int add_till_double_quote(o_string *dest, struct in_str *input) | 4535 | static void add_till_double_quote(o_string *dest, struct in_str *input) |
4530 | { | 4536 | { |
4531 | while (1) { | 4537 | while (1) { |
4532 | int ch = i_getch(input); | 4538 | int ch = i_getch(input); |
4533 | if (ch == EOF) { | 4539 | if (ch == EOF) { |
4534 | syntax_error_unterm_ch('"'); | 4540 | syntax_error_unterm_ch('"'); |
4535 | return 1; | 4541 | /*xfunc_die(); - redundant */ |
4536 | } | 4542 | } |
4537 | if (ch == '"') | 4543 | if (ch == '"') |
4538 | return 0; | 4544 | return; |
4539 | if (ch == '\\') { /* \x. Copy both chars. */ | 4545 | if (ch == '\\') { /* \x. Copy both chars. */ |
4540 | o_addchr(dest, ch); | 4546 | o_addchr(dest, ch); |
4541 | ch = i_getch(input); | 4547 | ch = i_getch(input); |
4542 | } | 4548 | } |
4543 | o_addchr(dest, ch); | 4549 | o_addchr(dest, ch); |
4544 | if (ch == '`') { | 4550 | if (ch == '`') { |
4545 | if (add_till_backquote(dest, input)) | 4551 | add_till_backquote(dest, input); |
4546 | return 1; | ||
4547 | o_addchr(dest, ch); | 4552 | o_addchr(dest, ch); |
4548 | continue; | 4553 | continue; |
4549 | } | 4554 | } |
@@ -4564,22 +4569,22 @@ static int add_till_double_quote(o_string *dest, struct in_str *input) | |||
4564 | * Example Output | 4569 | * Example Output |
4565 | * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST | 4570 | * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST |
4566 | */ | 4571 | */ |
4567 | static int add_till_backquote(o_string *dest, struct in_str *input) | 4572 | static void add_till_backquote(o_string *dest, struct in_str *input) |
4568 | { | 4573 | { |
4569 | while (1) { | 4574 | while (1) { |
4570 | int ch = i_getch(input); | 4575 | int ch = i_getch(input); |
4571 | if (ch == EOF) { | 4576 | if (ch == EOF) { |
4572 | syntax_error_unterm_ch('`'); | 4577 | syntax_error_unterm_ch('`'); |
4573 | return 1; | 4578 | /*xfunc_die(); - redundant */ |
4574 | } | 4579 | } |
4575 | if (ch == '`') | 4580 | if (ch == '`') |
4576 | return 0; | 4581 | return; |
4577 | if (ch == '\\') { | 4582 | if (ch == '\\') { |
4578 | /* \x. Copy both chars unless it is \` */ | 4583 | /* \x. Copy both chars unless it is \` */ |
4579 | int ch2 = i_getch(input); | 4584 | int ch2 = i_getch(input); |
4580 | if (ch2 == EOF) { | 4585 | if (ch2 == EOF) { |
4581 | syntax_error_unterm_ch('`'); | 4586 | syntax_error_unterm_ch('`'); |
4582 | return 1; | 4587 | /*xfunc_die(); - redundant */ |
4583 | } | 4588 | } |
4584 | if (ch2 != '`' && ch2 != '$' && ch2 != '\\') | 4589 | if (ch2 != '`' && ch2 != '$' && ch2 != '\\') |
4585 | o_addchr(dest, ch); | 4590 | o_addchr(dest, ch); |
@@ -4600,14 +4605,14 @@ static int add_till_backquote(o_string *dest, struct in_str *input) | |||
4600 | * echo $(echo 'TEST)' BEST) TEST) BEST | 4605 | * echo $(echo 'TEST)' BEST) TEST) BEST |
4601 | * echo $(echo \(\(TEST\) BEST) ((TEST) BEST | 4606 | * echo $(echo \(\(TEST\) BEST) ((TEST) BEST |
4602 | */ | 4607 | */ |
4603 | static int add_till_closing_paren(o_string *dest, struct in_str *input, bool dbl) | 4608 | static void add_till_closing_paren(o_string *dest, struct in_str *input, bool dbl) |
4604 | { | 4609 | { |
4605 | int count = 0; | 4610 | int count = 0; |
4606 | while (1) { | 4611 | while (1) { |
4607 | int ch = i_getch(input); | 4612 | int ch = i_getch(input); |
4608 | if (ch == EOF) { | 4613 | if (ch == EOF) { |
4609 | syntax_error_unterm_ch(')'); | 4614 | syntax_error_unterm_ch(')'); |
4610 | return 1; | 4615 | /*xfunc_die(); - redundant */ |
4611 | } | 4616 | } |
4612 | if (ch == '(') | 4617 | if (ch == '(') |
4613 | count++; | 4618 | count++; |
@@ -4623,14 +4628,12 @@ static int add_till_closing_paren(o_string *dest, struct in_str *input, bool dbl | |||
4623 | } | 4628 | } |
4624 | o_addchr(dest, ch); | 4629 | o_addchr(dest, ch); |
4625 | if (ch == '\'') { | 4630 | if (ch == '\'') { |
4626 | if (add_till_single_quote(dest, input)) | 4631 | add_till_single_quote(dest, input); |
4627 | return 1; | ||
4628 | o_addchr(dest, ch); | 4632 | o_addchr(dest, ch); |
4629 | continue; | 4633 | continue; |
4630 | } | 4634 | } |
4631 | if (ch == '"') { | 4635 | if (ch == '"') { |
4632 | if (add_till_double_quote(dest, input)) | 4636 | add_till_double_quote(dest, input); |
4633 | return 1; | ||
4634 | o_addchr(dest, ch); | 4637 | o_addchr(dest, ch); |
4635 | continue; | 4638 | continue; |
4636 | } | 4639 | } |
@@ -4639,13 +4642,12 @@ static int add_till_closing_paren(o_string *dest, struct in_str *input, bool dbl | |||
4639 | ch = i_getch(input); | 4642 | ch = i_getch(input); |
4640 | if (ch == EOF) { | 4643 | if (ch == EOF) { |
4641 | syntax_error_unterm_ch(')'); | 4644 | syntax_error_unterm_ch(')'); |
4642 | return 1; | 4645 | /*xfunc_die(); - redundant */ |
4643 | } | 4646 | } |
4644 | o_addchr(dest, ch); | 4647 | o_addchr(dest, ch); |
4645 | continue; | 4648 | continue; |
4646 | } | 4649 | } |
4647 | } | 4650 | } |
4648 | return 0; | ||
4649 | } | 4651 | } |
4650 | #endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT */ | 4652 | #endif /* ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT */ |
4651 | 4653 | ||
@@ -4786,8 +4788,7 @@ static int handle_dollar(o_string *as_string, | |||
4786 | # if !BB_MMU | 4788 | # if !BB_MMU |
4787 | pos = dest->length; | 4789 | pos = dest->length; |
4788 | # endif | 4790 | # endif |
4789 | if (add_till_closing_paren(dest, input, true)) | 4791 | add_till_closing_paren(dest, input, true); |
4790 | return 1; | ||
4791 | # if !BB_MMU | 4792 | # if !BB_MMU |
4792 | if (as_string) { | 4793 | if (as_string) { |
4793 | o_addstr(as_string, dest->data + pos); | 4794 | o_addstr(as_string, dest->data + pos); |
@@ -4805,8 +4806,7 @@ static int handle_dollar(o_string *as_string, | |||
4805 | # if !BB_MMU | 4806 | # if !BB_MMU |
4806 | pos = dest->length; | 4807 | pos = dest->length; |
4807 | # endif | 4808 | # endif |
4808 | if (add_till_closing_paren(dest, input, false)) | 4809 | add_till_closing_paren(dest, input, false); |
4809 | return 1; | ||
4810 | # if !BB_MMU | 4810 | # if !BB_MMU |
4811 | if (as_string) { | 4811 | if (as_string) { |
4812 | o_addstr(as_string, dest->data + pos); | 4812 | o_addstr(as_string, dest->data + pos); |
@@ -4862,8 +4862,7 @@ static int parse_stream_dquoted(o_string *as_string, | |||
4862 | /* note: can't move it above ch == dquote_end check! */ | 4862 | /* note: can't move it above ch == dquote_end check! */ |
4863 | if (ch == EOF) { | 4863 | if (ch == EOF) { |
4864 | syntax_error_unterm_ch('"'); | 4864 | syntax_error_unterm_ch('"'); |
4865 | debug_printf_parse("parse_stream_dquoted return 1: unterminated \"\n"); | 4865 | /*xfunc_die(); - redundant */ |
4866 | return 1; | ||
4867 | } | 4866 | } |
4868 | next = '\0'; | 4867 | next = '\0'; |
4869 | if (ch != '\n') { | 4868 | if (ch != '\n') { |
@@ -4872,11 +4871,9 @@ static int parse_stream_dquoted(o_string *as_string, | |||
4872 | debug_printf_parse(": ch=%c (%d) escape=%d\n", | 4871 | debug_printf_parse(": ch=%c (%d) escape=%d\n", |
4873 | ch, ch, dest->o_escape); | 4872 | ch, ch, dest->o_escape); |
4874 | if (ch == '\\') { | 4873 | if (ch == '\\') { |
4875 | //TODO: check interactive behavior | ||
4876 | if (next == EOF) { | 4874 | if (next == EOF) { |
4877 | syntax_error("\\<eof>"); | 4875 | syntax_error("\\<eof>"); |
4878 | debug_printf_parse("parse_stream_dquoted return 1: \\<eof>\n"); | 4876 | xfunc_die(); |
4879 | return 1; | ||
4880 | } | 4877 | } |
4881 | /* bash: | 4878 | /* bash: |
4882 | * "The backslash retains its special meaning [in "..."] | 4879 | * "The backslash retains its special meaning [in "..."] |
@@ -4904,8 +4901,7 @@ static int parse_stream_dquoted(o_string *as_string, | |||
4904 | //int pos = dest->length; | 4901 | //int pos = dest->length; |
4905 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4902 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4906 | o_addchr(dest, 0x80 | '`'); | 4903 | o_addchr(dest, 0x80 | '`'); |
4907 | if (add_till_backquote(dest, input)) | 4904 | add_till_backquote(dest, input); |
4908 | return 1; | ||
4909 | o_addchr(dest, SPECIAL_VAR_SYMBOL); | 4905 | o_addchr(dest, SPECIAL_VAR_SYMBOL); |
4910 | //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); | 4906 | //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); |
4911 | goto again; | 4907 | goto again; |
@@ -4982,16 +4978,17 @@ static struct pipe *parse_stream(char **pstring, | |||
4982 | 4978 | ||
4983 | if (heredoc_cnt) { | 4979 | if (heredoc_cnt) { |
4984 | syntax_error_unterm_str("here document"); | 4980 | syntax_error_unterm_str("here document"); |
4985 | goto parse_error; | 4981 | xfunc_die(); |
4986 | } | 4982 | } |
4987 | if (done_word(&dest, &ctx)) { | 4983 | if (done_word(&dest, &ctx)) { |
4988 | goto parse_error; | 4984 | xfunc_die(); |
4989 | } | 4985 | } |
4990 | o_free(&dest); | 4986 | o_free(&dest); |
4991 | done_pipe(&ctx, PIPE_SEQ); | 4987 | done_pipe(&ctx, PIPE_SEQ); |
4992 | pi = ctx.list_head; | 4988 | pi = ctx.list_head; |
4993 | /* If we got nothing... */ | 4989 | /* If we got nothing... */ |
4994 | // TODO: test script consisting of just "&" | 4990 | /* (this makes bare "&" cmd a no-op. |
4991 | * bash says: "syntax error near unexpected token '&'") */ | ||
4995 | if (pi->num_cmds == 0 | 4992 | if (pi->num_cmds == 0 |
4996 | IF_HAS_KEYWORDS( && pi->res_word == RES_NONE) | 4993 | IF_HAS_KEYWORDS( && pi->res_word == RES_NONE) |
4997 | ) { | 4994 | ) { |
@@ -5182,7 +5179,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5182 | case '\\': | 5179 | case '\\': |
5183 | if (next == EOF) { | 5180 | if (next == EOF) { |
5184 | syntax_error("\\<eof>"); | 5181 | syntax_error("\\<eof>"); |
5185 | goto parse_error; | 5182 | xfunc_die(); |
5186 | } | 5183 | } |
5187 | o_addchr(&dest, '\\'); | 5184 | o_addchr(&dest, '\\'); |
5188 | ch = i_getch(input); | 5185 | ch = i_getch(input); |
@@ -5205,7 +5202,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5205 | ch = i_getch(input); | 5202 | ch = i_getch(input); |
5206 | if (ch == EOF) { | 5203 | if (ch == EOF) { |
5207 | syntax_error_unterm_ch('\''); | 5204 | syntax_error_unterm_ch('\''); |
5208 | goto parse_error; | 5205 | /*xfunc_die(); - redundant */ |
5209 | } | 5206 | } |
5210 | nommu_addchr(&ctx.as_string, ch); | 5207 | nommu_addchr(&ctx.as_string, ch); |
5211 | if (ch == '\'') | 5208 | if (ch == '\'') |
@@ -5232,8 +5229,7 @@ static struct pipe *parse_stream(char **pstring, | |||
5232 | #if !BB_MMU | 5229 | #if !BB_MMU |
5233 | pos = dest.length; | 5230 | pos = dest.length; |
5234 | #endif | 5231 | #endif |
5235 | if (add_till_backquote(&dest, input)) | 5232 | add_till_backquote(&dest, input); |
5236 | goto parse_error; | ||
5237 | #if !BB_MMU | 5233 | #if !BB_MMU |
5238 | o_addstr(&ctx.as_string, dest.data + pos); | 5234 | o_addstr(&ctx.as_string, dest.data + pos); |
5239 | o_addchr(&ctx.as_string, '`'); | 5235 | o_addchr(&ctx.as_string, '`'); |
@@ -5976,7 +5972,8 @@ static int builtin_cd(char **argv) | |||
5976 | const char *newdir = argv[1]; | 5972 | const char *newdir = argv[1]; |
5977 | if (newdir == NULL) { | 5973 | if (newdir == NULL) { |
5978 | /* bash does nothing (exitcode 0) if HOME is ""; if it's unset, | 5974 | /* bash does nothing (exitcode 0) if HOME is ""; if it's unset, |
5979 | * bash says "bash: cd: HOME not set" and does nothing (exitcode 1) | 5975 | * bash says "bash: cd: HOME not set" and does nothing |
5976 | * (exitcode 1) | ||
5980 | */ | 5977 | */ |
5981 | newdir = getenv("HOME") ? : "/"; | 5978 | newdir = getenv("HOME") ? : "/"; |
5982 | } | 5979 | } |
@@ -6024,14 +6021,42 @@ static int builtin_exit(char **argv) | |||
6024 | static int builtin_export(char **argv) | 6021 | static int builtin_export(char **argv) |
6025 | { | 6022 | { |
6026 | if (*++argv == NULL) { | 6023 | if (*++argv == NULL) { |
6027 | // TODO: | ||
6028 | // ash emits: export VAR='VAL' | ||
6029 | // bash: declare -x VAR="VAL" | ||
6030 | // (both also escape as needed (quotes, $, etc)) | ||
6031 | char **e = environ; | 6024 | char **e = environ; |
6032 | if (e) | 6025 | if (e) { |
6033 | while (*e) | 6026 | while (*e) { |
6027 | #if 0 | ||
6034 | puts(*e++); | 6028 | puts(*e++); |
6029 | #else | ||
6030 | /* ash emits: export VAR='VAL' | ||
6031 | * bash: declare -x VAR="VAL" | ||
6032 | * we follow ash example */ | ||
6033 | const char *s = *e++; | ||
6034 | const char *p = strchr(s, '='); | ||
6035 | |||
6036 | if (!p) /* wtf? take next variable */ | ||
6037 | continue; | ||
6038 | /* export var= */ | ||
6039 | printf("export %.*s", (int)(p - s) + 1, s); | ||
6040 | s = p + 1; | ||
6041 | while (*s) { | ||
6042 | if (*s != '\'') { | ||
6043 | p = strchrnul(s, '\''); | ||
6044 | /* print 'xxxx' */ | ||
6045 | printf("'%.*s'", (int)(p - s), s); | ||
6046 | if (*p == '\0') | ||
6047 | break; | ||
6048 | s = p; | ||
6049 | } | ||
6050 | /* s points to '; print ''...'''" */ | ||
6051 | putchar('"'); | ||
6052 | do putchar('\''); while (*++s == '\''); | ||
6053 | putchar('"'); | ||
6054 | } | ||
6055 | putchar('\n'); | ||
6056 | #endif | ||
6057 | } | ||
6058 | fflush(stdout); | ||
6059 | } | ||
6035 | return EXIT_SUCCESS; | 6060 | return EXIT_SUCCESS; |
6036 | } | 6061 | } |
6037 | 6062 | ||
diff --git a/shell/hush_test/hush-misc/export.right b/shell/hush_test/hush-misc/export.right new file mode 100644 index 000000000..4df2e3858 --- /dev/null +++ b/shell/hush_test/hush-misc/export.right | |||
@@ -0,0 +1,6 @@ | |||
1 | export aaa1="'''" | ||
2 | export aaa2= | ||
3 | export aaa3="'''"'abc' | ||
4 | export aaa4='def'"'''" | ||
5 | export aaa5="'''"'abc'"'''"'def'"'''" | ||
6 | Done | ||
diff --git a/shell/hush_test/hush-misc/export.tests b/shell/hush_test/hush-misc/export.tests new file mode 100755 index 000000000..87a27ecce --- /dev/null +++ b/shell/hush_test/hush-misc/export.tests | |||
@@ -0,0 +1,7 @@ | |||
1 | export aaa1="'''" | ||
2 | export aaa2="" | ||
3 | export aaa3="'''abc" | ||
4 | export aaa4="def'''" | ||
5 | export aaa5="'''abc'''def'''" | ||
6 | export | grep aaa.= | ||
7 | echo Done | ||