diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | Src/parse.c | 6 | ||||
-rw-r--r-- | Src/text.c | 19 | ||||
-rw-r--r-- | Src/zsh.h | 12 | ||||
-rw-r--r-- | Test/A04redirect.ztst | 52 |
5 files changed, 87 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog index 49c76fe05..ca3eb3ccd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-03-14 Peter Stephenson <pws@csr.com> + + * 24711: Src/parse.c, Src/text.c, Src/zsh.h, + Test/A04redirect.ztst: fix re-presentation of here-documents + munged internally to here-strings. + 2008-03-13 Peter Stephenson <pws@csr.com> * 24705: configure.ac, Config/defs.mk.in, Src/zsh.mdd, diff --git a/Src/parse.c b/Src/parse.c index af3cba9d3..54543a642 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1861,7 +1861,7 @@ par_redir(int *rp, char *idstring) void setheredoc(int pc, int type, char *str) { - ecbuf[pc] = WCB_REDIR(type); + ecbuf[pc] = WCB_REDIR(type | REDIR_FROM_HEREDOC_MASK); ecbuf[pc + 2] = ecstrcode(str); } @@ -2409,6 +2409,10 @@ ecgetredirs(Estate s) r->type = WC_REDIR_TYPE(code); r->fd1 = *s->pc++; r->name = ecgetstr(s, EC_DUP, NULL); + if (WC_REDIR_FROM_HEREDOC(code)) + r->flags = REDIRF_FROM_HEREDOC; + else + r->flags = 0; if (WC_REDIR_VARID(code)) r->varid = ecgetstr(s, EC_DUP, NULL); else diff --git a/Src/text.c b/Src/text.c index 593c25776..7fdc5757f 100644 --- a/Src/text.c +++ b/Src/text.c @@ -831,17 +831,22 @@ getredirs(LinkList redirs) taddstr(fstr[f->type]); if (f->type != REDIR_MERGEIN && f->type != REDIR_MERGEOUT) taddchr(' '); - if (f->type == REDIR_HERESTR && !has_token(f->name)) { + if (f->type == REDIR_HERESTR && + (f->flags & REDIRF_FROM_HEREDOC)) { /* * Strings that came from here-documents are converted * to here strings without quotation, so add that - * now. If tokens are already present taddstr() - * will do the right thing (anyway, adding more - * quotes certainly isn't right in that case). + * now. If tokens are present we need to do double quoting. */ - taddchr('\''); - taddstr(quotestring(f->name, NULL, QT_SINGLE)); - taddchr('\''); + if (!has_token(f->name)) { + taddchr('\''); + taddstr(quotestring(f->name, NULL, QT_SINGLE)); + taddchr('\''); + } else { + taddchr('"'); + taddstr(quotestring(f->name, NULL, QT_DOUBLE)); + taddchr('"'); + } } else taddstr(f->name); taddchr(' '); diff --git a/Src/zsh.h b/Src/zsh.h index fb4d51ecd..495f51ad2 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -309,7 +309,10 @@ enum { REDIR_OUTPIPE /* > >(...) */ }; #define REDIR_TYPE_MASK (0x1f) +/* Redir using {var} syntax */ #define REDIR_VARID_MASK (0x20) +/* Mark here-string that came from a here-document */ +#define REDIR_FROM_HEREDOC_MASK (0x40) #define IS_WRITE_FILE(X) ((X)>=REDIR_WRITE && (X)<=REDIR_READWRITE) #define IS_APPEND_REDIR(X) (IS_WRITE_FILE(X) && ((X) & 2)) @@ -550,10 +553,18 @@ struct conddef { #define CONDDEF(name, flags, handler, min, max, condid) \ { NULL, name, flags, handler, min, max, condid, NULL } +/* Flags for redirections */ + +enum { + /* Mark a here-string that came from a here-document */ + REDIRF_FROM_HEREDOC = 1 +}; + /* tree element for redirection lists */ struct redir { int type; + int flags; int fd1, fd2; char *name; char *varid; @@ -744,6 +755,7 @@ struct eccstr { #define WC_REDIR_TYPE(C) ((int)(wc_data(C) & REDIR_TYPE_MASK)) #define WC_REDIR_VARID(C) ((int)(wc_data(C) & REDIR_VARID_MASK)) +#define WC_REDIR_FROM_HEREDOC(C) ((int)(wc_data(C) & REDIR_FROM_HEREDOC_MASK)) #define WCB_REDIR(T) wc_bld(WC_REDIR, (T)) /* Size of redir is 4 words if REDIR_VARID_MASK is set, else 3 */ #define WC_REDIR_WORDS(C) (WC_REDIR_VARID(C) ? 4 : 3) diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst index 2813d0e28..e27442c25 100644 --- a/Test/A04redirect.ztst +++ b/Test/A04redirect.ztst @@ -82,6 +82,58 @@ >b >c +# The following tests check that output of parsed here-documents works. +# This isn't completely trivial because we convert the here-documents +# internally to here-strings. So we check again that we can output +# the reevaluated here-strings correctly. Hence there are three slightly +# different stages. We don't care how the output actually looks, so +# we don't test that. + heretest() { + print First line + cat <<-HERE + $foo$foo met celeste 'but with extra' "stuff to test quoting" + HERE + print Last line + } + heretest + eval "$(functions heretest)" + heretest + eval "$(functions heretest)" + heretest +0:Re-evaluation of function output with here document, unquoted +>First line +>barbar met celeste 'but with extra' "stuff to test quoting" +>Last line +>First line +>barbar met celeste 'but with extra' "stuff to test quoting" +>Last line +>First line +>barbar met celeste 'but with extra' "stuff to test quoting" +>Last line + + heretest() { + print First line + cat <<' HERE' + $foo$foo met celeste 'but with extra' "stuff to test quoting" + HERE + print Last line + } + heretest + eval "$(functions heretest)" + heretest + eval "$(functions heretest)" + heretest +0:Re-evaluation of function output with here document, quoted +>First line +> $foo$foo met celeste 'but with extra' "stuff to test quoting" +>Last line +>First line +> $foo$foo met celeste 'but with extra' "stuff to test quoting" +>Last line +>First line +> $foo$foo met celeste 'but with extra' "stuff to test quoting" +>Last line + # # exec tests: perform these in subshells so if they fail the # shell won't exit. |