diff options
author | Denys Vlasenko | 2018-04-11 01:33:54 +0200 |
---|---|---|
committer | Denys Vlasenko | 2018-04-11 01:34:46 +0200 |
commit | 0403bedccc17c8ea3059523e32ea615e5df4bc26 (patch) | |
tree | f7cd40adbfc0ee1ccd0bad90e319daf146ad5937 /shell | |
parent | 89e9d5534d0e8879803ed9dbb25dff3989c31202 (diff) | |
download | busybox-0403bedccc17c8ea3059523e32ea615e5df4bc26.zip busybox-0403bedccc17c8ea3059523e32ea615e5df4bc26.tar.gz |
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 'shell')
-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 523fc1a..735fbef 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -5076,6 +5076,14 @@ static struct pipe *parse_stream(char **pstring, } nommu_addchr(&ctx.as_string, ch); + /* Handle "'" and "\" first, as they won't play nice with + * i_peek_and_eat_bkslash_nl() anyway: + * echo z\\ + * and + * echo '\ + * ' + * would break. + */ if (ch == '\'') { ctx.word.has_quoted_part = 1; next = i_getch(input); @@ -5101,19 +5109,34 @@ static struct pipe *parse_stream(char **pstring, } continue; /* get next char */ } + if (ch == '\\') { + /*nommu_addchr(&ctx.as_string, '\\'); - already done */ + o_addchr(&ctx.word, '\\'); + ch = i_getch(input); + if (ch == EOF) { + /* Testcase: eval 'echo Ok\' */ - next = '\0'; - if (ch != '\n' && ch != '\\') { - /* Not on '\': do not break the case of "echo z\\": - * on 2nd '\', i_peek_and_eat_bkslash_nl() - * would stop and try to read next line, - * not letting the command to execute. +#if 0 /* bash-4.3.43 was removing backslash, but 4.4.19 retains it, most other shells too */ + /* Remove trailing '\' from ctx.as_string */ + ctx.as_string.data[--ctx.as_string.length] = '\0'; +#endif + continue; /* get next char */ + } + /* Example: echo Hello \2>file + * we need to know that word 2 is quoted */ - next = i_peek_and_eat_bkslash_nl(input); + ctx.word.has_quoted_part = 1; + nommu_addchr(&ctx.as_string, ch); + o_addchr(&ctx.word, ch); + continue; /* get next char */ } + next = '\0'; + if (ch != '\n') + next = i_peek_and_eat_bkslash_nl(input); + is_special = "{}<>;&|()#" /* special outside of "str" */ - "\\$\"" IF_HUSH_TICK("`") /* always special */ + "$\"" IF_HUSH_TICK("`") /* always special */ SPECIAL_VAR_SYMBOL_STR; /* Are { and } special here? */ if (ctx.command->argv /* word [word]{... - non-special */ @@ -5401,26 +5424,6 @@ static struct pipe *parse_stream(char **pstring, /* non-comment #: "echo a#b" etc */ o_addchr(&ctx.word, ch); continue; /* get next char */ - case '\\': - /*nommu_addchr(&ctx.as_string, '\\'); - already done */ - o_addchr(&ctx.word, '\\'); - ch = i_getch(input); - if (ch == EOF) { - /* Testcase: eval 'echo Ok\' */ - -#if 0 /* bash-4.3.43 was removing backslash, but 4.4.19 retains it, most other shells too */ - /* Remove trailing '\' from ctx.as_string */ - ctx.as_string.data[--ctx.as_string.length] = '\0'; -#endif - continue; /* get next char */ - } - /* Example: echo Hello \2>file - * we need to know that word 2 is quoted - */ - ctx.word.has_quoted_part = 1; - nommu_addchr(&ctx.as_string, ch); - o_addchr(&ctx.word, ch); - continue; /* get next char */ case '$': if (!parse_dollar(&ctx.as_string, &ctx.word, input, /*quote_mask:*/ 0)) { debug_printf_parse("parse_stream parse error: " |