From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8210 invoked by alias); 22 Feb 2012 17:28:55 -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: 30256 Received: (qmail 2664 invoked from network); 22 Feb 2012 17:28:44 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 Received-SPF: none (ns1.primenet.com.au: domain at closedmail.com does not designate permitted sender hosts) From: Bart Schaefer Message-id: <120222092827.ZM24425@torch.brasslantern.com> Date: Wed, 22 Feb 2012 09:28:27 -0800 In-reply-to: <20120222095248.1ea8140b@pwslap01u.europe.root.pri> Comments: In reply to Peter Stephenson "Re: let unset array element remove compatible with bash" (Feb 22, 9:52am) References: <120221210106.ZM13374@torch.brasslantern.com> <20120222095248.1ea8140b@pwslap01u.europe.root.pri> X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: Subject: Re: let unset array element remove compatible with bash MIME-version: 1.0 Content-type: text/plain; charset=us-ascii On Feb 22, 9:52am, Peter Stephenson wrote: } } So it's not simply a case of unconditionally deleting an element. I } think you need to check the element is present in the first place. Is there a straightforward way to do that? The code in subst.c that handles ${+var[x]} is rather convoluted, and every combination of getvalue()/fetchvalue() that I've tried always returns non-NULL for subscripted expressions. Which probably explains this comment in subst.c: /* * Indicates we have tried to get a value in v but that was * unset. I don't quite understand why (v == NULL) isn't * good enough, but there are places where we seem to need * to second guess whether a value is a real value or not. */ int vunset = 0; Then there's this horror, which appears to be fetching the entire array to call arrlen() on it, just to discover whether one of the elements is not set: /* Value retrieved from parameter/subexpression is scalar */ if (v->pm->node.flags & PM_ARRAY) { /* * Although the value is a scalar, the parameter * itself is an array. Presumably this is due to * being quoted, or doing single substitution or something, * TODO: we're about to do some definitely stringy * stuff, so something like this bit is probably * necessary. However, I'd like to leave any * necessary joining of arrays until this point * to avoid the multsub() horror. */ int tmplen = arrlen(v->pm->gsu.a->getfn(v->pm)); if (v->start < 0) v->start += tmplen + ((v->flags & VALFLAG_INV) ? 1 : 0); if (!(v->flags & VALFLAG_INV) && (v->start >= tmplen || v->start < 0)) vunset = 1; } Gaah.