[git commit] hush: optimize parse_stream()

Denys Vlasenko vda.linux at googlemail.com
Tue Apr 10 23:34:46 UTC 2018


commit: https://git.busybox.net/busybox/commit/?id=0403bedccc17c8ea3059523e32ea615e5df4bc26
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

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 at googlemail.com>
---
 shell/hush.c | 59 +++++++++++++++++++++++++++++++----------------------------
 1 file 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,
 		}
 		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: "


More information about the busybox-cvs mailing list