aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/ash.c111
-rw-r--r--shell/ash_test/ash-heredoc/heredoc_empty.right3
-rwxr-xr-xshell/ash_test/ash-heredoc/heredoc_empty.tests8
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 */
10308static char *
10309pfgets(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 */
10966static union node *andor(void); 10940static union node *andor(void);
10967static union node *pipeline(void); 10941static 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 */
11148static int
11149noexpand(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
11164static void 11118static void
11165parsefname(void) 11119parsefname(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 */
11817checkend: { 11769checkend: {
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 @@
1OK
2OK
3OK
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 @@
1unset a
2cat <<- $a
3 OK
4$a
5cat <<- ""
6 OK
7
8echo OK