diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-11 01:33:54 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-11 01:34:46 +0200 |
commit | 0403bedccc17c8ea3059523e32ea615e5df4bc26 (patch) | |
tree | f7cd40adbfc0ee1ccd0bad90e319daf146ad5937 /shell/hush.c | |
parent | 89e9d5534d0e8879803ed9dbb25dff3989c31202 (diff) | |
download | busybox-w32-0403bedccc17c8ea3059523e32ea615e5df4bc26.tar.gz busybox-w32-0403bedccc17c8ea3059523e32ea615e5df4bc26.tar.bz2 busybox-w32-0403bedccc17c8ea3059523e32ea615e5df4bc26.zip |
hush: optimize parse_stream()
Since we check for '\' anyway when we determine whether we can look ahead,
we can just check for *and handle* it there.
function old new delta
parse_stream 2751 2740 -11
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to '')
-rw-r--r-- | shell/hush.c | 59 |
1 files changed, 31 insertions, 28 deletions
diff --git a/shell/hush.c b/shell/hush.c index 523fc1a31..735fbef27 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -5076,6 +5076,14 @@ static struct pipe *parse_stream(char **pstring, | |||
5076 | } | 5076 | } |
5077 | nommu_addchr(&ctx.as_string, ch); | 5077 | nommu_addchr(&ctx.as_string, ch); |
5078 | 5078 | ||
5079 | /* Handle "'" and "\" first, as they won't play nice with | ||
5080 | * i_peek_and_eat_bkslash_nl() anyway: | ||
5081 | * echo z\\ | ||
5082 | * and | ||
5083 | * echo '\ | ||
5084 | * ' | ||
5085 | * would break. | ||
5086 | */ | ||
5079 | if (ch == '\'') { | 5087 | if (ch == '\'') { |
5080 | ctx.word.has_quoted_part = 1; | 5088 | ctx.word.has_quoted_part = 1; |
5081 | next = i_getch(input); | 5089 | next = i_getch(input); |
@@ -5101,19 +5109,34 @@ static struct pipe *parse_stream(char **pstring, | |||
5101 | } | 5109 | } |
5102 | continue; /* get next char */ | 5110 | continue; /* get next char */ |
5103 | } | 5111 | } |
5112 | if (ch == '\\') { | ||
5113 | /*nommu_addchr(&ctx.as_string, '\\'); - already done */ | ||
5114 | o_addchr(&ctx.word, '\\'); | ||
5115 | ch = i_getch(input); | ||
5116 | if (ch == EOF) { | ||
5117 | /* Testcase: eval 'echo Ok\' */ | ||
5104 | 5118 | ||
5105 | next = '\0'; | 5119 | #if 0 /* bash-4.3.43 was removing backslash, but 4.4.19 retains it, most other shells too */ |
5106 | if (ch != '\n' && ch != '\\') { | 5120 | /* Remove trailing '\' from ctx.as_string */ |
5107 | /* Not on '\': do not break the case of "echo z\\": | 5121 | ctx.as_string.data[--ctx.as_string.length] = '\0'; |
5108 | * on 2nd '\', i_peek_and_eat_bkslash_nl() | 5122 | #endif |
5109 | * would stop and try to read next line, | 5123 | continue; /* get next char */ |
5110 | * not letting the command to execute. | 5124 | } |
5125 | /* Example: echo Hello \2>file | ||
5126 | * we need to know that word 2 is quoted | ||
5111 | */ | 5127 | */ |
5112 | next = i_peek_and_eat_bkslash_nl(input); | 5128 | ctx.word.has_quoted_part = 1; |
5129 | nommu_addchr(&ctx.as_string, ch); | ||
5130 | o_addchr(&ctx.word, ch); | ||
5131 | continue; /* get next char */ | ||
5113 | } | 5132 | } |
5114 | 5133 | ||
5134 | next = '\0'; | ||
5135 | if (ch != '\n') | ||
5136 | next = i_peek_and_eat_bkslash_nl(input); | ||
5137 | |||
5115 | is_special = "{}<>;&|()#" /* special outside of "str" */ | 5138 | is_special = "{}<>;&|()#" /* special outside of "str" */ |
5116 | "\\$\"" IF_HUSH_TICK("`") /* always special */ | 5139 | "$\"" IF_HUSH_TICK("`") /* always special */ |
5117 | SPECIAL_VAR_SYMBOL_STR; | 5140 | SPECIAL_VAR_SYMBOL_STR; |
5118 | /* Are { and } special here? */ | 5141 | /* Are { and } special here? */ |
5119 | if (ctx.command->argv /* word [word]{... - non-special */ | 5142 | if (ctx.command->argv /* word [word]{... - non-special */ |
@@ -5401,26 +5424,6 @@ static struct pipe *parse_stream(char **pstring, | |||
5401 | /* non-comment #: "echo a#b" etc */ | 5424 | /* non-comment #: "echo a#b" etc */ |
5402 | o_addchr(&ctx.word, ch); | 5425 | o_addchr(&ctx.word, ch); |
5403 | continue; /* get next char */ | 5426 | continue; /* get next char */ |
5404 | case '\\': | ||
5405 | /*nommu_addchr(&ctx.as_string, '\\'); - already done */ | ||
5406 | o_addchr(&ctx.word, '\\'); | ||
5407 | ch = i_getch(input); | ||
5408 | if (ch == EOF) { | ||
5409 | /* Testcase: eval 'echo Ok\' */ | ||
5410 | |||
5411 | #if 0 /* bash-4.3.43 was removing backslash, but 4.4.19 retains it, most other shells too */ | ||
5412 | /* Remove trailing '\' from ctx.as_string */ | ||
5413 | ctx.as_string.data[--ctx.as_string.length] = '\0'; | ||
5414 | #endif | ||
5415 | continue; /* get next char */ | ||
5416 | } | ||
5417 | /* Example: echo Hello \2>file | ||
5418 | * we need to know that word 2 is quoted | ||
5419 | */ | ||
5420 | ctx.word.has_quoted_part = 1; | ||
5421 | nommu_addchr(&ctx.as_string, ch); | ||
5422 | o_addchr(&ctx.word, ch); | ||
5423 | continue; /* get next char */ | ||
5424 | case '$': | 5427 | case '$': |
5425 | if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { | 5428 | if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { |
5426 | debug_printf_parse("parse_stream parse error: " | 5429 | debug_printf_parse("parse_stream parse error: " |