From 5129820336782902f0dc43d7f196bb66c4579fb9 Mon Sep 17 00:00:00 2001 From: Sebastian Gniazdowski Date: Wed, 3 May 2023 14:47:01 +0059 Subject: Support the mksh's ${|func;} substitution --- Src/subst.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/Src/subst.c b/Src/subst.c index 974d6171e..abb458195 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -29,6 +29,7 @@ #include "zsh.mdh" #include "subst.pro" +#include "exec.pro" #define LF_ARRAY 1 @@ -1860,8 +1861,17 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, * joining the array into a string (for compatibility with ksh/bash). */ int quoted_array_with_offset = 0; + /* Indicates ${|func;} */ + int rplyfunc = 0; + /* The name of the function to be ran by ${|...;} */ + char *cmdarg = NULL; + /* The length of the input string */ + int slen = 0; + /* The closing brace pointer */ + char *outbracep; *s++ = '\0'; + slen = strlen(s); /* * Nothing to do unless the character following the $ is * something we recognise. @@ -1889,6 +1899,41 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, if (c == Inbrace) { inbrace = 1; s++; + + /* Short-path for the function-running substitution ${|func;} + * The function name is extracted and called, and the + * substitution assigned. There's no (...)-flags processing, + * i.e. no ${|(U)func;}, because it looks quite awful and + * also requires a change to the manual, part about the + * substitution order. Use ${(U)${|func;}} instead, it looks + * cleaner. */ + if ( ((outbracep=strchr(s,Outbrace)) || + (outbracep=strchr(s,'}'))) && + (s[0] == Bar || s[0] == '|') && + outbracep[-1] == ';' ) + { + rplyfunc = 1; + cmdarg = dupstrpfx(s+1, outbracep-s-2); + s=outbracep; + + HashNode hn = NULL; + if( (hn = shfunctab->getnode(shfunctab, cmdarg)) ) { + /* Execute the shell function */ + doshfunc((Shfunc) hn, NULL, 1); + val = getsparam("REPLY"); + if (val) + vunset = 0; + else { + vunset = 1; + val = dupstring(""); + } + } else { + zerr("no such function: %s", cmdarg); + return NULL; + } + fetch_needed = 0; + } + /* * In ksh emulation a leading `!' is a special flag working * sort of like our (k). This is true only for arrays or @@ -2589,7 +2634,11 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, scanflags)) || (v->pm && (v->pm->node.flags & PM_UNSET)) || (v->flags & VALFLAG_EMPTY)) - vunset = 1; + { + if (!rplyfunc) { + vunset = 1; + } + } if (wantt) { /* -- 2.28.0