ash: use pgetc_eatbnl() in more places
authorDenys Vlasenko <vda.linux@googlemail.com>
Sat, 31 Mar 2018 17:21:31 +0000 (19:21 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sat, 31 Mar 2018 17:40:56 +0000 (19:40 +0200)
Part of upstream commit:

    Date:   Thu Mar 8 08:37:11 2018 +0100
    Author: Harald van Dijk <harald@gigawatt.nl>
    parser: use pgetc_eatbnl() in more places

    dash has a pgetc_eatbnl function in parser.c which skips any
    backslash-newline combinations. It's not used everywhere it could be.
    There is also some duplicated backslash-newline handling elsewhere in
    parser.c. Replace most of the calls to pgetc() with calls to
    pgetc_eatbnl() and remove the duplicated backslash-newline handling.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Not adding "readtoken1(pgetc_eatbnl(), DQSYNTAX..." changes, since
readtoken1() handles the "starts with backslash + newline" case itself.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c
shell/ash_test/ash-heredoc/heredoc_backslash1.right [new file with mode: 0644]
shell/ash_test/ash-heredoc/heredoc_backslash1.tests [new file with mode: 0755]
shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.right [new file with mode: 0644]
shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.tests [new file with mode: 0755]
shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.right [new file with mode: 0644]
shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.tests [new file with mode: 0755]

index 2ed802d2e2ed1707752a9c7523c0ad07df46f461..a7767b4f84424640701c44149f40fcf718005d9f 100644 (file)
@@ -12225,7 +12225,7 @@ parseredir: {
        np = stzalloc(sizeof(struct nfile));
        if (c == '>') {
                np->nfile.fd = 1;
-               c = pgetc();
+               c = pgetc_eatbnl();
                if (c == '>')
                        np->type = NAPPEND;
                else if (c == '|')
@@ -12247,7 +12247,7 @@ parseredir: {
 #endif
        else { /* c == '<' */
                /*np->nfile.fd = 0; - stzalloc did it */
-               c = pgetc();
+               c = pgetc_eatbnl();
                switch (c) {
                case '<':
                        if (sizeof(struct nfile) != sizeof(struct nhere)) {
@@ -12257,7 +12257,7 @@ parseredir: {
                        np->type = NHERE;
                        heredoc = stzalloc(sizeof(struct heredoc));
                        heredoc->here = np;
-                       c = pgetc();
+                       c = pgetc_eatbnl();
                        if (c == '-') {
                                heredoc->striptabs = 1;
                        } else {
@@ -12487,23 +12487,13 @@ parsebackq: {
                        int pc;
 
                        setprompt_if(needprompt, 2);
-                       pc = pgetc();
+                       pc = pgetc_eatbnl();
                        switch (pc) {
                        case '`':
                                goto done;
 
                        case '\\':
-                               pc = pgetc();
-                               if (pc == '\n') {
-                                       nlprompt();
-                                       /*
-                                        * If eating a newline, avoid putting
-                                        * the newline into the new character
-                                        * stream (via the STPUTC after the
-                                        * switch).
-                                        */
-                                       continue;
-                               }
+                               pc = pgetc(); /* or pgetc_eatbnl()? why (example)? */
                                if (pc != '\\' && pc != '`' && pc != '$'
                                 && (!dblquote || pc != '"')
                                ) {
@@ -12635,7 +12625,7 @@ xxreadtoken(void)
        }
        setprompt_if(needprompt, 2);
        for (;;) {                      /* until token or start of word found */
-               c = pgetc();
+               c = pgetc_eatbnl();
                if (c == ' ' || c == '\t' IF_ASH_ALIAS( || c == PEOA))
                        continue;
 
@@ -12644,11 +12634,7 @@ xxreadtoken(void)
                                continue;
                        pungetc();
                } else if (c == '\\') {
-                       if (pgetc() != '\n') {
-                               pungetc();
-                               break; /* return readtoken1(...) */
-                       }
-                       nlprompt();
+                       break; /* return readtoken1(...) */
                } else {
                        const char *p;
 
@@ -12695,7 +12681,7 @@ xxreadtoken(void)
        }
        setprompt_if(needprompt, 2);
        for (;;) {      /* until token or start of word found */
-               c = pgetc();
+               c = pgetc_eatbnl();
                switch (c) {
                case ' ': case '\t':
                IF_ASH_ALIAS(case PEOA:)
@@ -12705,30 +12691,23 @@ xxreadtoken(void)
                                continue;
                        pungetc();
                        continue;
-               case '\\':
-                       if (pgetc() == '\n') {
-                               nlprompt();
-                               continue;
-                       }
-                       pungetc();
-                       goto breakloop;
                case '\n':
                        nlnoprompt();
                        RETURN(TNL);
                case PEOF:
                        RETURN(TEOF);
                case '&':
-                       if (pgetc() == '&')
+                       if (pgetc_eatbnl() == '&')
                                RETURN(TAND);
                        pungetc();
                        RETURN(TBACKGND);
                case '|':
-                       if (pgetc() == '|')
+                       if (pgetc_eatbnl() == '|')
                                RETURN(TOR);
                        pungetc();
                        RETURN(TPIPE);
                case ';':
-                       if (pgetc() == ';')
+                       if (pgetc_eatbnl() == ';')
                                RETURN(TENDCASE);
                        pungetc();
                        RETURN(TSEMI);
@@ -12736,11 +12715,9 @@ xxreadtoken(void)
                        RETURN(TLP);
                case ')':
                        RETURN(TRP);
-               default:
-                       goto breakloop;
                }
+               break;
        }
- breakloop:
        return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
 #undef RETURN
 }
diff --git a/shell/ash_test/ash-heredoc/heredoc_backslash1.right b/shell/ash_test/ash-heredoc/heredoc_backslash1.right
new file mode 100644 (file)
index 0000000..6a61148
--- /dev/null
@@ -0,0 +1,43 @@
+Quoted heredoc:
+a\
+       b
+a\\
+       b
+ 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+       -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+ 123456 `echo  v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'`
+ 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-')
+c\
+
+Unquoted heredoc:
+a      b
+a\
+       b
+ 123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?-
+       -qwerty-\t-\-\"-\'-`-\--\z-\*-\?-
+ 123456 v-$a-\t-\-\"-\x-`-\--\z-\*-\?-
+ 123456 v-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-
+cEOF2
+
+Quoted -heredoc:
+a\
+b
+a\\
+b
+ 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+ 123456 `echo  v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'`
+ 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-')
+c\
+
+Unquoted -heredoc:
+a      b
+a\
+b
+ 123456 -qwerty-\t-\-\"-\'-`-\--\z-\*-\?-
+-qwerty-\t-\-\"-\'-`-\--\z-\*-\?-
+ 123456 v-$a-\t-\-\"-\x-`-\--\z-\*-\?-
+ 123456 v-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-
+cEOF4
+
+Done: 0
diff --git a/shell/ash_test/ash-heredoc/heredoc_backslash1.tests b/shell/ash_test/ash-heredoc/heredoc_backslash1.tests
new file mode 100755 (executable)
index 0000000..501af54
--- /dev/null
@@ -0,0 +1,70 @@
+# Test for correct handling of backslashes.
+# Note that some lines in each heredoc start with a tab.
+
+a=qwerty
+
+echo Quoted heredoc:
+cat <<"EOF1"
+a\
+       b
+a\\
+       b
+ 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+       -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+ 123456 `echo  v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'`
+ 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-')
+c\
+EOF1
+echo
+
+echo Unquoted heredoc:
+cat <<EOF2
+a\
+       b
+a\\
+       b
+ 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+       -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+ 123456 `echo  v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'`
+ 123456 $(echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-')
+c\
+EOF2
+EOF2
+echo
+
+echo Quoted -heredoc:
+cat <<-"EOF3"
+a\
+       b
+a\\
+       b
+ 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+       -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+ 123456 `echo  v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-'`
+ 123456 $(echo v'-$a-\t-\\-\"-\'-\`-\--\z-\*-\?-')
+c\
+       EOF3
+# In -heredoc case the marker is detected even if it is indented.
+echo
+
+echo Unquoted -heredoc:
+cat <<-EOF4
+a\
+       b
+a\\
+       b
+ 123456 -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+       -$a-\t-\\-\"-\'-\`-\--\z-\*-\?-
+ 123456 `echo  v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-'`
+ 123456 $(echo v'-$a-\t-\\-\"-\x-\`-\--\z-\*-\?-')
+c\
+EOF4
+       EOF4
+# The marker is not detected if preceding line ends in backslash.
+# TODO: marker should be detected even if it is split by line continuation:
+# EOF\
+# 4
+# but currently hush doesn't do it. (Tab before "4" is not allowed, though.)
+echo
+
+echo "Done: $?"
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.right b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.right
new file mode 100644 (file)
index 0000000..fdb7ebd
--- /dev/null
@@ -0,0 +1,8 @@
+heredoc0
+Ok0:0
+heredoc1
+Ok1:0
+heredoc2
+Ok2:0
+heredoc3
+Ok4:0
diff --git a/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.tests b/shell/ash_test/ash-heredoc/heredoc_bkslash_newline1.tests
new file mode 100755 (executable)
index 0000000..584edd0
--- /dev/null
@@ -0,0 +1,25 @@
+cat <\
+<\
+EOF
+heredoc0
+EOF
+echo Ok0:$?
+
+cat <<\
+ EOF
+heredoc1
+EOF
+echo Ok1:$?
+
+cat <<\
+- EOF
+heredoc2
+       EOF
+echo Ok2:$?
+
+cat <\
+<\
+- EOF
+heredoc3
+       EOF
+echo Ok4:$?
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.right b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.right
new file mode 100644 (file)
index 0000000..fdb7ebd
--- /dev/null
@@ -0,0 +1,8 @@
+heredoc0
+Ok0:0
+heredoc1
+Ok1:0
+heredoc2
+Ok2:0
+heredoc3
+Ok4:0
diff --git a/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.tests b/shell/hush_test/hush-heredoc/heredoc_bkslash_newline1.tests
new file mode 100755 (executable)
index 0000000..584edd0
--- /dev/null
@@ -0,0 +1,25 @@
+cat <\
+<\
+EOF
+heredoc0
+EOF
+echo Ok0:$?
+
+cat <<\
+ EOF
+heredoc1
+EOF
+echo Ok1:$?
+
+cat <<\
+- EOF
+heredoc2
+       EOF
+echo Ok2:$?
+
+cat <\
+<\
+- EOF
+heredoc3
+       EOF
+echo Ok4:$?