summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko2018-04-11 01:33:54 +0200
committerDenys Vlasenko2018-04-11 01:34:46 +0200
commit0403bedccc17c8ea3059523e32ea615e5df4bc26 (patch)
treef7cd40adbfc0ee1ccd0bad90e319daf146ad5937 /shell
parent89e9d5534d0e8879803ed9dbb25dff3989c31202 (diff)
downloadbusybox-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.c59
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: "