From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 21511 invoked by alias); 10 Jan 2011 18:21:25 -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: 28617 Received: (qmail 2898 invoked from network); 10 Jan 2011 18:21:22 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW, SPF_HELO_PASS autolearn=ham version=3.3.1 Received-SPF: none (ns1.primenet.com.au: domain at csr.com does not designate permitted sender hosts) Date: Mon, 10 Jan 2011 18:20:30 +0000 From: Peter Stephenson To: Rocky Bernstein , Subject: Re: zsh -n doesn't grok associate array indexes? Message-ID: <20110110182030.6792fec1@pwslap01u.europe.root.pri> In-Reply-To: References: Organization: Cambridge Silicon Radio X-Mailer: Claws Mail 3.7.8 (GTK+ 2.20.1; i386-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 10 Jan 2011 18:20:30.0802 (UTC) FILETIME=[10594B20:01CBB0F3] X-Scanned-By: MailControl A_10_80_00 (www.mailcontrol.com) on 10.71.1.135 On Mon, 10 Jan 2011 12:18:09 -0500 Rocky Bernstein wrote: > I tried zsh -n to see how good a tool it might be for lint checking. > Overall it works very well. > > However I ran into a problem when using a string associative array > index. Here's a sample run: > > $ cat /tmp/zsh-bug.sh > > typeset -A hash > > hash['display']=5 > > echo ${hash['display']} > > $ zsh /tmp/zsh-bug.sh > > 5 > > $ zsh -n /tmp/zsh-bug.sh > > /tmp/zsh-bug.sh:2: bad math expression: operand expected at > > `'display'' /tmp/zsh-bug.sh:3: bad math expression: operand > > expected at `'display'' $ zsh --version > > zsh 4.3.10 (i686-pc-linux-gnu) Certainly, a subscript is expected to be a math expression unless you've explicitly told it the variable is an associative array. However, given that it's not executing the assignment I can see how you'd want it to be otherwise here... Actually, it looks like it was executing the assignment, which must surely be wrong, too, since, as here, the resulting operation may be nonsense. I don't think anyone's ever sanity-checked NO_EXEC to this depth before, let alone optimised it for useful checking, so you could run across anything. I've run across one myself: we do globbing, which might throw up a "no match" error. Presumably doing any form of globbing is pointless; I'm not sure how far to go into the code before it's not worth it, but 'not very far' is the default answer, since the expression hasn't been through previous expansion stages properly. Index: Src/glob.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/glob.c,v retrieving revision 1.74 diff -p -u -r1.74 glob.c --- Src/glob.c 5 Dec 2010 21:07:48 -0000 1.74 +++ Src/glob.c 10 Jan 2011 18:18:18 -0000 @@ -1111,7 +1111,7 @@ zglob(LinkList list, LinkNode np, int no struct globdata saved; /* saved glob state */ int nobareglob = !isset(BAREGLOBQUAL); - if (unset(GLOBOPT) || !haswilds(ostr)) { + if (unset(GLOBOPT) || !haswilds(ostr) || unset(EXECOPT)) { if (!nountok) untokenize(ostr); return; Index: Src/params.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/params.c,v retrieving revision 1.166 diff -p -u -r1.166 params.c --- Src/params.c 21 Dec 2010 16:54:30 -0000 1.166 +++ Src/params.c 10 Jan 2011 18:18:18 -0000 @@ -1055,6 +1055,14 @@ getarg(char **str, int *inv, Value v, in zlong num = 1, beg = 0, r = 0, quote_arg = 0; Patprog pprog = NULL; + /* + * If in NO_EXEC mode, the parameters won't be set up + * properly, so there's no point even doing any sanity checking. + * Just return 0 now. + */ + if (unset(EXECOPT)) + return 0; + ishash = (v->pm && PM_TYPE(v->pm->node.flags) == PM_HASHED); if (prevcharlen) *prevcharlen = 1; @@ -2230,6 +2238,8 @@ export_param(Param pm) mod_export void setstrvalue(Value v, char *val) { + if (unset(EXECOPT)) + return; if (v->pm->node.flags & PM_READONLY) { zerr("read-only variable: %s", v->pm->node.nam); zsfree(val); @@ -2361,6 +2371,8 @@ setnumvalue(Value v, mnumber val) { char buf[BDIGBUFSIZE], *p; + if (unset(EXECOPT)) + return; if (v->pm->node.flags & PM_READONLY) { zerr("read-only variable: %s", v->pm->node.nam); return; @@ -2398,6 +2410,8 @@ setnumvalue(Value v, mnumber val) mod_export void setarrvalue(Value v, char **val) { + if (unset(EXECOPT)) + return; if (v->pm->node.flags & PM_READONLY) { zerr("read-only variable: %s", v->pm->node.nam); freearray(val); @@ -2808,6 +2822,8 @@ sethparam(char *s, char **val) errflag = 1; return NULL; } + if (unset(EXECOPT)) + return; queue_signals(); if (!(v = fetchvalue(&vbuf, &s, 1, SCANPM_ASSIGNING))) createparam(t, PM_HASHED); @@ -2846,6 +2862,8 @@ setnparam(char *s, mnumber val) errflag = 1; return NULL; } + if (unset(EXECOPT)) + return; queue_signals(); ss = strchr(s, '['); v = getvalue(&vbuf, &s, 1); Index: Test/E01options.ztst =================================================================== RCS file: /cvsroot/zsh/zsh/Test/E01options.ztst,v retrieving revision 1.23 diff -p -u -r1.23 E01options.ztst --- Test/E01options.ztst 22 Oct 2010 16:32:36 -0000 1.23 +++ Test/E01options.ztst 10 Jan 2011 18:18:18 -0000 @@ -344,6 +344,15 @@ 0:NO_EXEC option >before + (setopt noexec + typeset -A hash + hash['this is a string']) +0:NO_EXEC option should not attempt to parse subscripts + + (setopt noexec nomatch + echo *NonExistentFile*) +0:NO_EXEC option should not do globbing + setopt NO_eval_lineno eval 'print $LINENO' setopt eval_lineno -- Peter Stephenson Software Engineer Tel: +44 (0)1223 692070 Cambridge Silicon Radio Limited Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, UK Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom