hush: fix heredoc_bkslash_newline1.tests failure
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 31 Mar 2018 18:16:31 +0000 (20:16 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 31 Mar 2018 18:16:31 +0000 (20:16 +0200)
function                                             old     new   delta
parse_stream                                        2787    2827     +40
builtin_type                                         117     115      -2

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

index 01d8f5935d94e15c23ad8defc9bca5fdfc03d7ce..533d45ac33686dc7d56241af476f326c01421c94 100644 (file)
@@ -2694,6 +2694,42 @@ static int i_peek2(struct in_str *i)
        return ch;
 }
 
+static int i_getch_and_eat_bkslash_nl(struct in_str *input)
+{
+       for (;;) {
+               int ch, ch2;
+
+               ch = i_getch(input);
+               if (ch != '\\')
+                       return ch;
+               ch2 = i_peek(input);
+               if (ch2 != '\n')
+                       return ch;
+               /* backslash+newline, skip it */
+               i_getch(input);
+       }
+}
+
+/* Note: this function _eats_ \<newline> pairs, safe to use plain
+ * i_getch() after it instead of i_getch_and_eat_bkslash_nl().
+ */
+static int i_peek_and_eat_bkslash_nl(struct in_str *input)
+{
+       for (;;) {
+               int ch, ch2;
+
+               ch = i_peek(input);
+               if (ch != '\\')
+                       return ch;
+               ch2 = i_peek2(input);
+               if (ch2 != '\n')
+                       return ch;
+               /* backslash+newline, skip it */
+               i_getch(input);
+               i_getch(input);
+       }
+}
+
 static void setup_file_in_str(struct in_str *i, FILE *f)
 {
        memset(i, 0, sizeof(*i));
@@ -4014,7 +4050,7 @@ static int parse_redirect(struct parse_context *ctx,
                if (dup_num == REDIRFD_SYNTAX_ERR)
                        return 1;
        } else {
-               int ch = i_peek(input);
+               int ch = i_peek_and_eat_bkslash_nl(input);
                dup_num = (ch == '-'); /* HEREDOC_SKIPTABS bit is 1 */
                if (dup_num) { /* <<-... */
                        ch = i_getch(input);
@@ -4024,7 +4060,7 @@ static int parse_redirect(struct parse_context *ctx,
        }
 
        if (style == REDIRECT_OVERWRITE && dup_num == REDIRFD_TO_FILE) {
-               int ch = i_peek(input);
+               int ch = i_peek_and_eat_bkslash_nl(input);
                if (ch == '|') {
                        /* >|FILE redirect ("clobbering" >).
                         * Since we do not support "set -o noclobber" yet,
@@ -4343,39 +4379,6 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
        /* command remains "open", available for possible redirects */
 }
 
-static int i_getch_and_eat_bkslash_nl(struct in_str *input)
-{
-       for (;;) {
-               int ch, ch2;
-
-               ch = i_getch(input);
-               if (ch != '\\')
-                       return ch;
-               ch2 = i_peek(input);
-               if (ch2 != '\n')
-                       return ch;
-               /* backslash+newline, skip it */
-               i_getch(input);
-       }
-}
-
-static int i_peek_and_eat_bkslash_nl(struct in_str *input)
-{
-       for (;;) {
-               int ch, ch2;
-
-               ch = i_peek(input);
-               if (ch != '\\')
-                       return ch;
-               ch2 = i_peek2(input);
-               if (ch2 != '\n')
-                       return ch;
-               /* backslash+newline, skip it */
-               i_getch(input);
-               i_getch(input);
-       }
-}
-
 #if ENABLE_HUSH_TICK || ENABLE_FEATURE_SH_MATH || ENABLE_HUSH_DOLLAR_OPS
 /* Subroutines for copying $(...) and `...` things */
 static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
@@ -5181,6 +5184,8 @@ static struct pipe *parse_stream(char **pstring,
                                goto parse_error;
                        }
                        redir_style = REDIRECT_OVERWRITE;
+                       if (next == '\\')
+                               next = i_peek_and_eat_bkslash_nl(input);
                        if (next == '>') {
                                redir_style = REDIRECT_APPEND;
                                ch = i_getch(input);
@@ -5201,6 +5206,8 @@ static struct pipe *parse_stream(char **pstring,
                                goto parse_error;
                        }
                        redir_style = REDIRECT_INPUT;
+                       if (next == '\\')
+                               next = i_peek_and_eat_bkslash_nl(input);
                        if (next == '<') {
                                redir_style = REDIRECT_HEREDOC;
                                heredoc_cnt++;