From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9337 invoked by alias); 25 Feb 2017 22:48:16 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 40640 Received: (qmail 14367 invoked from network); 25 Feb 2017 22:48:16 -0000 X-Qmail-Scanner-Diagnostics: from park01.gkg.net by f.primenet.com.au (envelope-from , uid 7791) with qmail-scanner-2.11 (clamdscan: 0.99.2/21882. spamassassin: 3.4.1. Clear:RC:0(205.235.26.22):SA:0(0.5/5.0):. Processed in 1.042809 secs); 25 Feb 2017 22:48:16 -0000 X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=0.5 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_SORBS_SPAM,RP_MATCHES_RCVD,T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.1 X-Envelope-From: SRS0=di5J=2G=brasslantern.com=schaefer@bounces.park01.gkg.net X-Qmail-Scanner-Mime-Attachments: | X-Qmail-Scanner-Zip-Files: | Received-SPF: none (ns1.primenet.com.au: domain at bounces.park01.gkg.net does not designate permitted sender hosts) X-Virus-Scanned: by amavisd-new at gkg.net Authentication-Results: amavisd4.gkg.net (amavisd-new); dkim=pass (2048-bit key) header.d=brasslantern-com.20150623.gappssmtp.com X-Greylist: from auto-whitelisted by SQLgrey-1.8.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=brasslantern-com.20150623.gappssmtp.com; s=20150623; h=from:message-id:date:to:subject:mime-version; bh=htqvGKGn0I8rupJGU97ccJN/WZb7IBBmaihU1lJq3n4=; b=C0FmzxsN0/Ti+FDJKFwcFm6EG7+y0wViHrVgB3pdWwvLYz+bU8UogmtnMTNXM2XVkz ItOfAtIDUZiwngfVEU2M9I0LOu2+bY7aXWZqvDCT2BQD5CSzypQsf31c3/BRWfIjb3Ha OTKDEfW7x2wUBPtrTI8jtFOKpWn+9yqp1y+rH141PUIhr3ADF9UzaYFCSbrVuDKEdhNW gih9P3Be/jg/LhD4bPSXa8CToCN37K0Sm+KvJno6aKWiq/PltxUIH60X1Op9O5C/1h6g bjelghCZEcmfs3QXV03ycFzb0/VFvoKU+40ucidk+RZtwMoFbR4xuodHSzkaYuqFZb3i Sqzg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:message-id:date:to:subject:mime-version; bh=htqvGKGn0I8rupJGU97ccJN/WZb7IBBmaihU1lJq3n4=; b=ZFvIpjJZpSQVbWmErxOEZDQedMpbMDU4/qH63cyYbam0zMNwioOtEkYp953eCKCGeE WA4G3zAdiVoQe2aORPWBbsRNbFku3Cm641yEU5WJDUyDRc7AlMW5jDyOsZ7M+y2rnnFY 3fEhSGJqabLXn7BBgdrQQVFB+YxAiwwyP9QUNokc5bZef3b3SNVNAGOSrVhLVHXINLw9 na1L7hzM4jWpaP1cHpzmEVpaBfgSBinj2GQG0VLUDaUDujZNdPL++s2Id1st4s7lXRAo 9EMzdu08BCpjhSCS9Z+lTKvpvJXMRkPq6fXqETm3FyfhOzV/BL/kUH0OUf6Sq72dJUal n2Tw== X-Gm-Message-State: AMke39nrhYjqsneUWvQtiXoSfd+9JliRJcBQu8sbfsSF5O//9QwPACieuUCV8baLT7fqhg== X-Received: by 10.176.5.200 with SMTP id e66mr4482558uae.108.1488062866070; Sat, 25 Feb 2017 14:47:46 -0800 (PST) From: Bart Schaefer Message-Id: <170225144755.ZM18979@torch.brasslantern.com> Date: Sat, 25 Feb 2017 14:47:55 -0800 X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-workers@zsh.org Subject: [PATCH] Forcing array interpretation in parameter substitution MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii } The problem is that nesting ${${...}} "wants" to treat the inner ${...} } as a scalar, and will do so unless something else forces it to be an } array. (f) doesn't accomplish that because $(dirs -v) produces only } one line of output with the final newline stripped, so there is nothing } for (f) to split on. (@) won't accomplish it because it only means } that things that are already arrays should remain so. } } So what can be done to force interpretation as an array here? I occurred to me in one of those "why didn't we do this before?" moments that there's no reason the (A) flag has to have meaning only in context of ${name=value}. I haven't found anything obviously wrong with the following patch and all tests still pass. diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo index 43ecd31..402afdb 100644 --- a/Doc/Zsh/expn.yo +++ b/Doc/Zsh/expn.yo @@ -955,15 +955,25 @@ This is distinct from em(field splitting) by the tt(f), tt(s) or tt(z) flags, which still applies within each array element. ) item(tt(A))( -Assign as an array parameter with `tt(${)...tt(=)...tt(})', +Convert the subsitution into an array expression, even if it otherwise +would be scalar. This has lower precedence than subscripting, so one +level of nested expansion is required in order that subscripts apply +to array elements. Thus tt(${${LPAR()A)tt(RPAR())var(name)tt(}[1]}) +yields the full value of var(name) when var(name) is scalar. + +This assigns an array parameter with `tt(${)...tt(=)...tt(})', `tt(${)...tt(:=)...tt(})' or `tt(${)...tt(::=)...tt(})'. -If this flag is repeated (as in `tt(AA)'), assign an associative +If this flag is repeated (as in `tt(AA)'), assigns an associative array parameter. Assignment is made before sorting or padding; if field splitting is active, the var(word) part is split before assignment. The var(name) part may be a subscripted range for ordinary arrays; when assigning an associative array, the var(word) part em(must) be converted to an array, for example by using `tt(${(AA)=)var(name)tt(=)...tt(})' to activate field splitting. + +Surrounding context such as additional nesting or use of the value +in a scalar assignment may cause the array to be joined back into +a single string again. ) item(tt(a))( Sort in array index order; when combined with `tt(O)' sort in reverse diff --git a/Src/subst.c b/Src/subst.c index 4df53bd..02dbe28 100644 --- a/Src/subst.c +++ b/Src/subst.c @@ -2902,6 +2902,7 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, } else setaparam(idbeg, a); isarr = 1; + arrasg = 0; } else { untokenize(val); setsparam(idbeg, ztrdup(val)); @@ -3784,6 +3785,16 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags, insertlinknode(l, n, dupstring(fstr)); /* appended, no incnode */ *fstr = '\0'; } + if (arrasg && !isarr) { + /* + * Caller requested this be forced to an array even if scalar. + * Any point in distinguishing arrasg == 2 (assoc array) here? + */ + l->list.flags |= LF_ARRAY; + aval = hmkarray(val); + isarr = 1; + DPUTS(!val, "value is NULL in paramsubst, empty array"); + } if (isarr) { char *x; char *y;