From ad2bd42c858aa7236e7b7404806d16b5b0efb6ac Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 23 Sep 2005 17:03:16 +0000 Subject: 21758: optimise =(<<<...) to run within the shell. --- ChangeLog | 6 +++++ Doc/Zsh/expn.yo | 9 +++++++ Src/exec.c | 67 +++++++++++++++++++++++++++++++++++++++++---------- Test/A04redirect.ztst | 8 ++++++ 4 files changed, 77 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index c2894399f..d4ce2f9d2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-09-23 Peter Stephenson + + * 21758: Doc/Zsh/expn.yo, Src/exec.c: optimise =(<<<...) to + replace an argument by a filename containing it within the + shell. + 2005-09-22 Peter Stephenson * unposted, c.f. 21752: Doc/Zsh/contrib.yo, diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index a75513b25..60c74cab1 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -340,6 +340,15 @@ process. This may be used instead of the tt(<) form for a program that expects to lseek (see manref(lseek)(2)) on the input file. +There is an optimisation for substitutions of the form +tt(=LPAR()<<<)var(arg)tt(RPAR()), where var(arg) is a single-word argument +to the here-string redirection tt(<<<). This form produces a file name +containing the value of var(arg) after any substitutions have been +performed. This is handled entirely within the current shell. This is +effectively the reverse of the special form tt($LPAR()<)var(arg)tt(RPAR()) +which treats var(arg) as a file name and replaces it with the file's +contents. + The tt(=) form is useful as both the tt(/dev/fd) and the named pipe implementation of tt(prog; if (prog != &dummy_eprog && wc_code(pc[0]) == WC_LIST && (WC_LIST_TYPE(pc[0]) & Z_END) && wc_code(pc[1]) == WC_SUBLIST && !WC_SUBLIST_FLAGS(pc[1]) && WC_SUBLIST_TYPE(pc[1]) == WC_SUBLIST_END && wc_code(pc[2]) == WC_PIPE && WC_PIPE_TYPE(pc[2]) == WC_PIPE_END && - wc_code(pc[3]) == WC_REDIR && WC_REDIR_TYPE(pc[3]) == REDIR_READ && + wc_code(pc[3]) == WC_REDIR && WC_REDIR_TYPE(pc[3]) == redir_type && !WC_REDIR_VARID(pc[3]) && !pc[4] && wc_code(pc[6]) == WC_SIMPLE && !WC_SIMPLE_ARGC(pc[6])) { + return dupstring(ecrawstr(prog, pc + 5, NULL)); + } + + return NULL; +} + +/* $(...) */ + +/**/ +LinkList +getoutput(char *cmd, int qt) +{ + Eprog prog; + int pipes[2]; + pid_t pid; + char *s; + + if (!(prog = parse_string(cmd))) + return NULL; + + if ((s = simple_redir_name(prog, REDIR_READ))) { /* $(< word) */ int stream; - char *s = dupstring(ecrawstr(prog, pc + 5, NULL)); singsub(&s); if (errflag) @@ -3101,6 +3118,7 @@ getoutputfile(char *cmd) char *nam; Eprog prog; int fd; + char *s; if (thisjob == -1) return NULL; @@ -3109,13 +3127,36 @@ getoutputfile(char *cmd) if (!(nam = gettempname(NULL, 0))) return NULL; + if ((s = simple_redir_name(prog, REDIR_HERESTR))) { + /* + * =(<<&- 1:Error closing file descriptor using readonly variable ?(eval):4: can't close file descriptor from readonly parameter myfd + +# This tests the here-string to filename optimisation; we can't +# test that it's actually being optimised, but we can test that it +# still works. + cat =(<<<$'This string has been replaced\nby a file containing it.\n') +0:Optimised here-string to filename +>This string has been replaced +>by a file containing it. -- cgit v1.2.3