diff options
-rw-r--r-- | shell/ash.c | 111 | ||||
-rw-r--r-- | shell/ash_test/ash-heredoc/heredoc_empty.right | 3 | ||||
-rwxr-xr-x | shell/ash_test/ash-heredoc/heredoc_empty.tests | 8 |
3 files changed, 52 insertions, 70 deletions
diff --git a/shell/ash.c b/shell/ash.c index 02b21510e..2bfec83e6 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -9991,6 +9991,7 @@ static smallint checkkwd; | |||
9991 | #define CHKALIAS 0x1 | 9991 | #define CHKALIAS 0x1 |
9992 | #define CHKKWD 0x2 | 9992 | #define CHKKWD 0x2 |
9993 | #define CHKNL 0x4 | 9993 | #define CHKNL 0x4 |
9994 | #define CHKEOFMARK 0x8 | ||
9994 | 9995 | ||
9995 | /* | 9996 | /* |
9996 | * Push a string back onto the input at this current parsefile level. | 9997 | * Push a string back onto the input at this current parsefile level. |
@@ -10303,31 +10304,6 @@ pgetc_without_PEOA(void) | |||
10303 | #endif | 10304 | #endif |
10304 | 10305 | ||
10305 | /* | 10306 | /* |
10306 | * Read a line from the script. | ||
10307 | */ | ||
10308 | static char * | ||
10309 | pfgets(char *line, int len) | ||
10310 | { | ||
10311 | char *p = line; | ||
10312 | int nleft = len; | ||
10313 | int c; | ||
10314 | |||
10315 | while (--nleft > 0) { | ||
10316 | c = pgetc_without_PEOA(); | ||
10317 | if (c == PEOF) { | ||
10318 | if (p == line) | ||
10319 | return NULL; | ||
10320 | break; | ||
10321 | } | ||
10322 | *p++ = c; | ||
10323 | if (c == '\n') | ||
10324 | break; | ||
10325 | } | ||
10326 | *p = '\0'; | ||
10327 | return line; | ||
10328 | } | ||
10329 | |||
10330 | /* | ||
10331 | * Undo a call to pgetc. Only two characters may be pushed back. | 10307 | * Undo a call to pgetc. Only two characters may be pushed back. |
10332 | * PEOF may be pushed back. | 10308 | * PEOF may be pushed back. |
10333 | */ | 10309 | */ |
@@ -10960,8 +10936,6 @@ raise_error_unexpected_syntax(int token) | |||
10960 | /* NOTREACHED */ | 10936 | /* NOTREACHED */ |
10961 | } | 10937 | } |
10962 | 10938 | ||
10963 | #define EOFMARKLEN 79 | ||
10964 | |||
10965 | /* parsing is heavily cross-recursive, need these forward decls */ | 10939 | /* parsing is heavily cross-recursive, need these forward decls */ |
10966 | static union node *andor(void); | 10940 | static union node *andor(void); |
10967 | static union node *pipeline(void); | 10941 | static union node *pipeline(void); |
@@ -11141,43 +11115,22 @@ fixredir(union node *n, const char *text, int err) | |||
11141 | } | 11115 | } |
11142 | } | 11116 | } |
11143 | 11117 | ||
11144 | /* | ||
11145 | * Returns true if the text contains nothing to expand (no dollar signs | ||
11146 | * or backquotes). | ||
11147 | */ | ||
11148 | static int | ||
11149 | noexpand(const char *text) | ||
11150 | { | ||
11151 | unsigned char c; | ||
11152 | |||
11153 | while ((c = *text++) != '\0') { | ||
11154 | if (c == CTLQUOTEMARK) | ||
11155 | continue; | ||
11156 | if (c == CTLESC) | ||
11157 | text++; | ||
11158 | else if (SIT(c, BASESYNTAX) == CCTL) | ||
11159 | return 0; | ||
11160 | } | ||
11161 | return 1; | ||
11162 | } | ||
11163 | |||
11164 | static void | 11118 | static void |
11165 | parsefname(void) | 11119 | parsefname(void) |
11166 | { | 11120 | { |
11167 | union node *n = redirnode; | 11121 | union node *n = redirnode; |
11168 | 11122 | ||
11123 | if (n->type == NHERE) | ||
11124 | checkkwd = CHKEOFMARK; | ||
11169 | if (readtoken() != TWORD) | 11125 | if (readtoken() != TWORD) |
11170 | raise_error_unexpected_syntax(-1); | 11126 | raise_error_unexpected_syntax(-1); |
11171 | if (n->type == NHERE) { | 11127 | if (n->type == NHERE) { |
11172 | struct heredoc *here = heredoc; | 11128 | struct heredoc *here = heredoc; |
11173 | struct heredoc *p; | 11129 | struct heredoc *p; |
11174 | int i; | ||
11175 | 11130 | ||
11176 | if (quoteflag == 0) | 11131 | if (quoteflag == 0) |
11177 | n->type = NXHERE; | 11132 | n->type = NXHERE; |
11178 | TRACE(("Here document %d\n", n->type)); | 11133 | TRACE(("Here document %d\n", n->type)); |
11179 | if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN) | ||
11180 | raise_error_syntax("illegal eof marker for << redirection"); | ||
11181 | rmescapes(wordtext, 0); | 11134 | rmescapes(wordtext, 0); |
11182 | here->eofmark = wordtext; | 11135 | here->eofmark = wordtext; |
11183 | here->next = NULL; | 11136 | here->next = NULL; |
@@ -11593,7 +11546,6 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11593 | /* c parameter is an unsigned char or PEOF or PEOA */ | 11546 | /* c parameter is an unsigned char or PEOF or PEOA */ |
11594 | char *out; | 11547 | char *out; |
11595 | size_t len; | 11548 | size_t len; |
11596 | char line[EOFMARKLEN + 1]; | ||
11597 | struct nodelist *bqlist; | 11549 | struct nodelist *bqlist; |
11598 | smallint quotef; | 11550 | smallint quotef; |
11599 | smallint dblquote; | 11551 | smallint dblquote; |
@@ -11816,6 +11768,9 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs) | |||
11816 | */ | 11768 | */ |
11817 | checkend: { | 11769 | checkend: { |
11818 | if (eofmark) { | 11770 | if (eofmark) { |
11771 | int markloc; | ||
11772 | char *p; | ||
11773 | |||
11819 | #if ENABLE_ASH_ALIAS | 11774 | #if ENABLE_ASH_ALIAS |
11820 | if (c == PEOA) | 11775 | if (c == PEOA) |
11821 | c = pgetc_without_PEOA(); | 11776 | c = pgetc_without_PEOA(); |
@@ -11825,27 +11780,42 @@ checkend: { | |||
11825 | c = pgetc_without_PEOA(); | 11780 | c = pgetc_without_PEOA(); |
11826 | } | 11781 | } |
11827 | } | 11782 | } |
11828 | if (c == *eofmark) { | 11783 | |
11829 | if (pfgets(line, sizeof(line)) != NULL) { | 11784 | markloc = out - (char *)stackblock(); |
11830 | char *p, *q; | 11785 | for (p = eofmark; STPUTC(c, out), *p; p++) { |
11831 | int cc; | 11786 | if (c != *p) |
11832 | 11787 | goto more_heredoc; | |
11833 | p = line; | 11788 | |
11834 | for (q = eofmark + 1;; p++, q++) { | 11789 | c = pgetc_without_PEOA(); |
11835 | cc = *p; | 11790 | } |
11836 | if (cc == '\n') | 11791 | |
11837 | cc = 0; | 11792 | if (c == '\n' || c == PEOF) { |
11838 | if (!*q || cc != *q) | 11793 | c = PEOF; |
11839 | break; | 11794 | g_parsefile->linno++; |
11840 | } | 11795 | needprompt = doprompt; |
11841 | if (cc == *q) { | 11796 | } else { |
11842 | c = PEOF; | 11797 | int len_here; |
11843 | nlnoprompt(); | 11798 | |
11844 | } else { | 11799 | more_heredoc: |
11845 | pushstring(line, NULL); | 11800 | p = (char *)stackblock() + markloc + 1; |
11801 | len_here = out - p; | ||
11802 | |||
11803 | if (len_here) { | ||
11804 | len_here -= (c >= PEOF); | ||
11805 | c = p[-1]; | ||
11806 | |||
11807 | if (len_here) { | ||
11808 | char *str; | ||
11809 | |||
11810 | str = alloca(len_here + 1); | ||
11811 | *(char *)mempcpy(str, p, len_here) = '\0'; | ||
11812 | |||
11813 | pushstring(str, NULL); | ||
11846 | } | 11814 | } |
11847 | } | 11815 | } |
11848 | } | 11816 | } |
11817 | |||
11818 | STADJUST((char *)stackblock() + markloc - out, out); | ||
11849 | } | 11819 | } |
11850 | goto checkend_return; | 11820 | goto checkend_return; |
11851 | } | 11821 | } |
@@ -11939,7 +11909,8 @@ parsesub: { | |||
11939 | int typeloc; | 11909 | int typeloc; |
11940 | 11910 | ||
11941 | c = pgetc_eatbnl(); | 11911 | c = pgetc_eatbnl(); |
11942 | if (c > 255 /* PEOA or PEOF */ | 11912 | if ((checkkwd & CHKEOFMARK) |
11913 | || c > 255 /* PEOA or PEOF */ | ||
11943 | || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) | 11914 | || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) |
11944 | ) { | 11915 | ) { |
11945 | #if BASH_DOLLAR_SQUOTE | 11916 | #if BASH_DOLLAR_SQUOTE |
diff --git a/shell/ash_test/ash-heredoc/heredoc_empty.right b/shell/ash_test/ash-heredoc/heredoc_empty.right new file mode 100644 index 000000000..0eabe3671 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_empty.right | |||
@@ -0,0 +1,3 @@ | |||
1 | OK | ||
2 | OK | ||
3 | OK | ||
diff --git a/shell/ash_test/ash-heredoc/heredoc_empty.tests b/shell/ash_test/ash-heredoc/heredoc_empty.tests new file mode 100755 index 000000000..3629bc6d1 --- /dev/null +++ b/shell/ash_test/ash-heredoc/heredoc_empty.tests | |||
@@ -0,0 +1,8 @@ | |||
1 | unset a | ||
2 | cat <<- $a | ||
3 | OK | ||
4 | $a | ||
5 | cat <<- "" | ||
6 | OK | ||
7 | |||
8 | echo OK | ||