hush: simplify \<newline> code, part 3
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 10 Apr 2018 12:20:48 +0000 (14:20 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 10 Apr 2018 12:27:08 +0000 (14:27 +0200)
function                                             old     new   delta
parse_stream                                        2780    2762     -18

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/hush.c

index 3c6718648d0b8750c34fe38e4c49717ca7d42416..6cd85cc4dc4323783f6f5f15f0ee64e9eb9a7054 100644 (file)
@@ -5052,19 +5052,43 @@ static struct pipe *parse_stream(char **pstring,
                }
                nommu_addchr(&ctx.as_string, ch);
 
+               if (ch == '\'') {
+                       ctx.word.has_quoted_part = 1;
+                       next = i_getch(input);
+                       if (next == '\'' && !ctx.pending_redirect)
+                               goto insert_empty_quoted_str_marker;
+
+                       ch = next;
+                       while (1) {
+                               if (ch == EOF) {
+                                       syntax_error_unterm_ch('\'');
+                                       goto parse_error;
+                               }
+                               nommu_addchr(&ctx.as_string, ch);
+                               if (ch == '\'')
+                                       break;
+                               if (ch == SPECIAL_VAR_SYMBOL) {
+                                       /* Convert raw ^C to corresponding special variable reference */
+                                       o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
+                                       o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
+                               }
+                               o_addqchr(&ctx.word, ch);
+                               ch = i_getch(input);
+                       }
+                       continue; /* get next char */
+               }
+
                next = '\0';
-               if (ch != '\n') {
-                       /* Do not break this case:
-                        *  echo '\
-                        *  '
-                        * and
-                        *  echo z\\
+               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.
                         */
-                       next = (ch == '\'' || ch == '\\') ? i_peek(input) : i_peek_and_eat_bkslash_nl(input);
-///
+                       next = i_peek_and_eat_bkslash_nl(input);
                }
 
-               is_special = "{}<>;&|()#'" /* special outside of "str" */
+               is_special = "{}<>;&|()#" /* special outside of "str" */
                                "\\$\"" IF_HUSH_TICK("`") /* always special */
                                SPECIAL_VAR_SYMBOL_STR;
                /* Are { and } special here? */
@@ -5252,7 +5276,7 @@ static struct pipe *parse_stream(char **pstring,
                                return ctx.list_head;
                        }
                }
- skip_end_trigger:
+
                if (is_blank)
                        continue;
 
@@ -5278,7 +5302,7 @@ static struct pipe *parse_stream(char **pstring,
 #endif
                        if (parse_redirect(&ctx, redir_fd, redir_style, input))
                                goto parse_error;
-                       continue; /* back to top of while (1) */
+                       continue; /* get next char */
                case '<':
                        redir_fd = redirect_opt_num(&ctx.word);
                        if (done_word(&ctx)) {
@@ -5304,7 +5328,7 @@ static struct pipe *parse_stream(char **pstring,
 #endif
                        if (parse_redirect(&ctx, redir_fd, redir_style, input))
                                goto parse_error;
-                       continue; /* back to top of while (1) */
+                       continue; /* get next char */
                case '#':
                        if (ctx.word.length == 0 && !ctx.word.has_quoted_part) {
                                /* skip "#comment" */
@@ -5325,23 +5349,11 @@ static struct pipe *parse_stream(char **pstring,
                                        if (ch == EOF)
                                                break;
                                }
-                               continue; /* back to top of while (1) */
-                       }
-                       break;
-#if 0 /* looks like we never reach this code */
-               case '\\':
-                       if (next == '\n') {
-                               /* It's "\<newline>" */
-#if !BB_MMU
-                               /* Remove trailing '\' from ctx.as_string */
-                               ctx.as_string.data[--ctx.as_string.length] = '\0';
-#endif
-                               ch = i_getch(input); /* eat it */
-                               continue; /* back to top of while (1) */
+                               continue; /* get next char */
                        }
                        break;
-#endif
                }
+ skip_end_trigger:
 
                if (ctx.is_assignment == MAYBE_ASSIGNMENT
                 /* check that we are not in word in "a=1 2>word b=1": */
@@ -5366,20 +5378,19 @@ static struct pipe *parse_stream(char **pstring,
                        o_addchr(&ctx.word, ch);
                        continue; /* get next char */
                case '\\':
-                       if (next == EOF) {
+                       /*nommu_addchr(&ctx.as_string, '\\'); - already done */
+                       o_addchr(&ctx.word, '\\');
+                       ch = i_getch(input);
+                       if (ch == EOF) {
 //TODO: in ". FILE" containing "cmd\" (no newline) bash ignores last "\"
                                syntax_error("\\<eof>");
                                xfunc_die();
                        }
-                       ch = i_getch(input);
-                       /* note: ch != '\n' (that case does not reach this place) */
-                       o_addchr(&ctx.word, '\\');
-                       /*nommu_addchr(&ctx.as_string, '\\'); - already done */
-                       o_addchr(&ctx.word, ch);
-                       nommu_addchr(&ctx.as_string, ch);
                        /* 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)) {
@@ -5388,33 +5399,12 @@ static struct pipe *parse_stream(char **pstring,
                                goto parse_error;
                        }
                        continue; /* get next char */
-               case '\'':
-                       ctx.word.has_quoted_part = 1;
-                       if (next == '\'' && !ctx.pending_redirect)
-                               goto insert_empty_quoted_str_marker;
-                       while (1) {
-                               ch = i_getch(input);
-                               if (ch == EOF) {
-                                       syntax_error_unterm_ch('\'');
-                                       goto parse_error;
-                               }
-                               nommu_addchr(&ctx.as_string, ch);
-                               if (ch == '\'')
-                                       break;
-                               if (ch == SPECIAL_VAR_SYMBOL) {
-                                       /* Convert raw ^C to corresponding special variable reference */
-                                       o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
-                                       o_addchr(&ctx.word, SPECIAL_VAR_QUOTED_SVS);
-                               }
-                               o_addqchr(&ctx.word, ch);
-                       }
-                       continue; /* get next char */
                case '"':
                        ctx.word.has_quoted_part = 1;
                        if (next == '"' && !ctx.pending_redirect) {
+                               i_getch(input); /* eat second " */
  insert_empty_quoted_str_marker:
                                nommu_addchr(&ctx.as_string, next);
-                               i_getch(input); /* eat second ' */
                                o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
                                o_addchr(&ctx.word, SPECIAL_VAR_SYMBOL);
                                continue; /* get next char */