From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22983 invoked by alias); 30 May 2014 19:03:22 -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: 32630 Received: (qmail 13350 invoked from network); 30 May 2014 19:03:05 -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 X-Originating-IP: [86.6.157.246] X-Spam: 0 X-Authority: v=2.1 cv=TM7LSjVa c=1 sm=1 tr=0 a=BvYiZ/UW0Fmn8Wufq9dPrg==:117 a=BvYiZ/UW0Fmn8Wufq9dPrg==:17 a=NLZqzBF-AAAA:8 a=pRTl07La5iUA:10 a=uObrxnre4hsA:10 a=kj9zAlcOel0A:10 a=q2GGsy2AAAAA:8 a=ZGDrcH-yNFHMS62XTYMA:9 a=Jwykwl1s1p_iebMS:21 a=eW84TjwpYrJFBbDk:21 a=CjuIK1q_8ugA:10 a=I6wTmPyJxzYA:10 a=_dQi-Dcv4p4A:10 Date: Fri, 30 May 2014 19:57:34 +0100 From: Peter Stephenson To: Zsh Hackers' List Subject: Re: globbing in conditional expressions Message-ID: <20140530195734.1d9c5310@pws-pc.ntlworld.com> In-Reply-To: <140530085542.ZM18304@torch.brasslantern.com> References: <20140507154407.660eb500@pwslap01u.europe.root.pri> <20140508105522.GE2052@tarsus.local2> <20140508122045.3c68c3fa@pwslap01u.europe.root.pri> <140508083418.ZM14713@torch.brasslantern.com> <20140508201936.GB53652@isis.sigpipe.cz> <140513084117.ZM22925@torch.brasslantern.com> <20140514041908.GF2471@tarsus.local2> <140514001819.ZM23478@torch.brasslantern.com> <20140515092901.GC2174@tarsus.local2> <140515075003.ZM28035@torch.brasslantern.com> <20140526235216.GC1920@tarsus.local2> <140529205956.ZM17410@torch.brasslantern.com> <20140530094752.4a116629@pwslap01u.europe.root.pri> <140530085542.ZM18304@torch.brasslantern.com> X-Mailer: Claws Mail 3.8.0 (GTK+ 2.24.7; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Fri, 30 May 2014 08:55:42 -0700 Bart Schaefer wrote: > On May 30, 9:47am, Peter Stephenson wrote: > } But this is specific to zsh --- why are we using [ rather than [[ anyway? > > Because [[ ]] doesn't do globbing on its arguments, and this is a > filename generation rather than a pattern. We messed around a few weeks > ago with trying to make [[ ]] do globbing and ran into tokenization > conflicts. (Moved this to workers. No user serviceable parts here.) Oh, er, right... you make it sound as if knowing what's going on is somehow a positive thing. One thing we could do is make [[ ... = ... ]] expand its right hand argument the same way as normal command arguments when told to do so, so there's no retokenization. (There's no point for [ ] since the globbing has already happened.) Then we could simply join the arguments resulting from the glob --- there may just be one, but we shouldn't simply ignore multuple results. We wouldn't want this always to happen, since that's confusing, but we could signal it, for example, using the extended glob syntax (#q), which explicitly indicates a glob pattern --- it has no meaning at all in non-glob pattern matching. This would limit it's use to when extended globbing is on, but I think that's an entirely sensible limitation anyway. I think this patch does roughly the right thing. So, for example, in the zsh Src directory [[ "glob.c glob.o" = g*.?(#q) ]] is true. Of course you can have other qualifiers such as NY after the #q. Piecing together the various sorts of expansion from execmd() isn't trivial --- it's quite likely I've missed some subtlety, possibly not even very subtle, in the first hunk below. diff --git a/Functions/Zle/expand-absolute-path b/Functions/Zle/expand-absolute-path index b857576..a420d41 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -282,9 +282,20 @@ evalcond(Estate state, char *fromtest) right = dupstring(opat = ecrawstr(state->prog, state->pc, &htok)); - if (htok) - singsub(&right); + if (htok) { + if (!fromtest && + checkglobqual(right, strlen(right), 1, NULL)) { + LinkList args = newlinklist(); + addlinknode(args, right); + prefork(args, 0); + while (!errflag && args && nonempty(args) && + has_token((char *)peekfirst(args))) + zglob(args, firstnode(args), 0); + right = sepjoin(hlinklist2array(args, 0), NULL, 1); + } else + singsub(&right); + } save = (!(state->prog->flags & EF_HEAP) && char *s = *sp; !strcmp(opat, right) && pprog != dummy_patprog2); diff --git a/Src/glob.c b/Src/glob.c index 07dd7c2..01f8a6e 100644 --- a/Src/glob.c +++ b/Src/glob.c @@ -1061,6 +1061,65 @@ insert_glob_match(LinkList list, LinkNode next, char *data) insertlinknode(list, next, data); } +/* + * Return + * 1 if str ends in bare glob qualifiers + * 2 if str ends in non-bare glob qualifiers (#q) + * 0 otherwise. + * + * str is the string to check. + * sl is it's length (to avoid recalculation). + * nobareglob is 1 if bare glob qualifiers are not allowed. + * *sp, if sp is not null, wil be a pointer to the start parentheses. + */ + +/**/ +int +checkglobqual(char *str, int sl, int nobareglob, char **sp) +{ + char *s; + int paren, ret = 1; + + if (str[sl - 1] != Outpar) + return 0; + + /* Check these are really qualifiers, not a set of * + * alternatives or exclusions. We can be more * + * lenient with an explicit (#q) than with a bare * + * set of qualifiers. */ + paren = 0; + for (s = str + sl - 2; *s && (*s != Inpar || paren); s--) { + switch (*s) { + case Outpar: + paren++; /*FALLTHROUGH*/ + case Bar: + if (!zpc_disables[ZPC_BAR]) + nobareglob = 1; + break; + case Tilde: + if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_TILDE]) + nobareglob = 1; + break; + case Inpar: + paren--; + break; + } + } + if (*s != Inpar) + return 0; + if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH] && s[1] == Pound) { + if (s[2] != 'q') + return 0; + ret = 2; + } else if (nobareglob) + return 0; + + if (sp) + *sp = s; + + return ret; +} + /* Main entry point to the globbing code for filename globbing. * * np points to a node in the list list which will be expanded * * into a series of nodes. */ @@ -1118,7 +1177,7 @@ zglob(LinkList list, LinkNode np, int nountok) (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH])) { struct qual *newquals; char *s; - int sense, paren; + int sense, qualsfound; off_t data; char *sdata, *newcolonmod; int (*func) _((char *, Statptr, off_t, char *)); @@ -1148,40 +1207,7 @@ zglob(LinkList list, LinkNode np, int nountok) newquals = qo = qn = ql = NULL; sl = strlen(str); - if (str[sl - 1] != Outpar) - break; - - /* Check these are really qualifiers, not a set of * - * alternatives or exclusions. We can be more * - * lenient with an explicit (#q) than with a bare * - * set of qualifiers. */ - paren = 0; - for (s = str + sl - 2; *s && (*s != Inpar || paren); s--) { - switch (*s) { - case Outpar: - paren++; /*FALLTHROUGH*/ - case Bar: - if (!zpc_disables[ZPC_BAR]) - nobareglob = 1; - break; - case Tilde: - if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_TILDE]) - nobareglob = 1; - break; - case Inpar: - paren--; - break; - } - } - if (*s != Inpar) - break; - if (isset(EXTENDEDGLOB) && !zpc_disables[ZPC_HASH] && s[1] == Pound) { - if (s[2] == 'q') { - *s = 0; - s += 2; - } else - break; - } else if (nobareglob) + if (!(qualsfound = checkglobqual(str, sl, nobareglob, &s))) break; /* Real qualifiers found. */ @@ -1194,6 +1220,8 @@ zglob(LinkList list, LinkNode np, int nountok) str[sl-1] = 0; *s++ = 0; + if (qualsfound == 2) + s += 2; while (*s && !newcolonmod) { func = (int (*) _((char *, Statptr, off_t, char *)))0; if (idigit(*s)) { -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/