From: Bart Schaefer <schaefer@brasslantern.com>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: Re: [PATCH] Nofork capture of stdout
Date: Mon, 11 Sep 2023 10:03:42 -0700 [thread overview]
Message-ID: <CAH+w=7Y8a1191YDOKo3s=MhWCentJ-SMC9tQGnQx0O47d0eumA@mail.gmail.com> (raw)
In-Reply-To: <CAH+w=7YoWwHdrEXTWMbV4LSTNiAbh+RR5SC=TenjSj_KeQFYag@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 827 bytes --]
On Sun, Sep 10, 2023 at 9:34 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> Which is exactly what the appended patch does: Leverage
> getoutputfile() to create a temporary name, then write it and read it
> back.
While looking for some additional tests for this, I ran into an error
I'd never seen before:
process substitution =(<<<'') cannot be used here
This happens if there's no current job on which addfilelist() can hang
the temp name. I don't know if there's any way to trigger it in
"normal" usage.
The appended is probably better anyway, it's slightly less of a hack
than before. Replaces workers/52126 entirely, although the Doc hunk
is unchanged.
> Implementation question: It seems to be OK to tokenize() a string
> that has already been tokenize()d?
Any comment on that?
[-- Attachment #2: nofork-stdout.txt --]
[-- Type: text/plain, Size: 3890 bytes --]
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 7480076df..1dec2c0e6 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -1918,13 +1918,11 @@ except as noted for tt(REPLY), and var(param) should em(not) be declared
within the command. If var(param) names an array, array expansion rules
apply.
-COMMENT(To be implemented later:
A command enclosed in braces preceded by a dollar sign, and set off from
the braces by whitespace, like `tt(${ )...tt( })', is replaced by its
standard output. Like `tt(${|)...tt(})' and unlike
`tt($LPAR())...tt(RPAR())', the command executes in the current shell
context with function local behaviors and does not create a subshell.
-)
texinode(Arithmetic Expansion)(Brace Expansion)(Command Substitution)(Expansion)
sect(Arithmetic Expansion)
diff --git a/Src/subst.c b/Src/subst.c
index aae178f9e..764213c69 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -1862,6 +1862,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
int quoted_array_with_offset = 0;
/* Indicates ${|...;} */
char *rplyvar = NULL;
+ /* Indicates ${ ... ;} */
+ char *rplytmp = NULL;
*s++ = '\0';
/*
@@ -1904,7 +1906,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
* should not be part of command substitution in any case.
* Use ${(U)${|cmd;}} as you would for ${(U)$(cmd;)}.
*/
- if (*s == '|' || *s == Bar) {
+ if (*s == '|' || *s == Bar || inblank(*s)) {
char *outbracep = s;
char sav = *s;
*s = Inbrace;
@@ -1940,6 +1942,29 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
cmdarg = dupstrpfx(s+1, outbracep-s-1);
rplyvar = "REPLY";
}
+ if (inblank(*s)) {
+ /*
+ * Admittedly a hack. Take advantage of the enforced
+ * locality of REPLY and the semantics of $(<file) to
+ * construct a command to write/read a temporary file.
+ * Then fall through to the regular handling of $REPLY
+ * to manage word splitting, expansion flags, etc.
+ */
+ char *fmt = "{ %s ;} >| %s; REPLY=\"$(<%s)\""; /* 28 */
+ if ((rplytmp = gettempname(NULL, 1))) {
+ /* Prevent shenanigans with $TMPPREFIX */
+ char *tmpfile = quotestring(rplytmp, QT_BACKSLASH);
+ char *dummy = zhalloc(strlen(cmdarg) +
+ 2 * strlen(tmpfile) +
+ 28);
+ sprintf(dummy, fmt, cmdarg, tmpfile, tmpfile);
+ cmdarg = dummy;
+ } else {
+ /* TMPPREFIX not writable? */
+ cmdoutval = lastval;
+ cmdarg = NULL;
+ }
+ }
s = outbracep;
}
}
@@ -1967,9 +1992,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
}
}
+ if (rplytmp)
+ unlink(rplytmp);
if (rplyvar) {
if (strcmp(rplyvar, "REPLY") == 0) {
- if ((val = ztrdup(getsparam("REPLY"))))
+ if ((val = dupstring(getsparam("REPLY"))))
vunset = 0;
else {
vunset = 1;
diff --git a/Test/D10nofork.ztst b/Test/D10nofork.ztst
index 738a45b99..3f11f80f1 100644
--- a/Test/D10nofork.ztst
+++ b/Test/D10nofork.ztst
@@ -160,7 +160,7 @@ F:Why not use this error in the previous case as well?
?(eval):1: closing brace expected
purr ${ purr STDOUT }
-0f:capture stdout
+0:capture stdout
>STDOUT
# end PS2 stack tests
@@ -321,6 +321,16 @@ F:Fiddly here to get EOF past the test syntax
0:here-string behavior
>in a here string
+ <<<${ purr $'stdout as a here string' }
+0:another capture stdout
+>stdout as a here string
+
+ wrap=${| REPLY="REPLY in environment assignment" } typeset -p wrap
+ wrap=${ purr "capture in environment assignment" } typeset -p wrap
+0:assignment context
+>typeset -g wrap='REPLY in environment assignment'
+>typeset -g wrap='capture in environment assignment'
+
print -u $ZTST_fd ${ZTST_testname}: TEST COMPLETE
0:make sure we got to the end
F:some tests might silently break the test harness
prev parent reply other threads:[~2023-09-11 17:04 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-09-11 4:34 Bart Schaefer
2023-09-11 17:03 ` Bart Schaefer [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAH+w=7Y8a1191YDOKo3s=MhWCentJ-SMC9tQGnQx0O47d0eumA@mail.gmail.com' \
--to=schaefer@brasslantern.com \
--cc=zsh-workers@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).