zsh-workers
 help / color / mirror / code / Atom feed
* Bug in regexp operator when warn_create_global is in effect
@ 2017-02-02  7:37 ` Ronald Fischer
  2017-02-02  9:43   ` Peter Stephenson
  0 siblings, 1 reply; 10+ messages in thread
From: Ronald Fischer @ 2017-02-02  7:37 UTC (permalink / raw)
  To: zsh-workers

Consider the following program:

   #!/bin/zsh
   function f {
      [[ x =~ x ]]
   }
   setopt warn_create_global
   f

When run by zsh 5.2 (x86_64-ubuntu-linux-gnu), I get the error messages:

f:1: scalar parameter MATCH created globally in function f
f:1: numeric parameter MBEGIN created globally in function f
f:1: numeric parameter MEND created globally in function f

While it is correct, that regexp matching sets, as side effect, the
variables mentioned here, it doesn't, IMHO, make much sense that a zsh
user, who not even *uses* these variables, receives these error
messages. If the user had to pay attention to those variables which
automatically spring into existence by zsh language constructs, doing a
cd inside a function should equally well raise the message "parameter
OLDPWD created globally in function".

I suggest that the variables MATCH, MBEGIN and MEND are already created
by zsh
as global parameters during shell startup time. This would not trigger
the warning, if someone uses regexp matching inside functions.

Ronald


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Bug in regexp operator when warn_create_global is in effect
  2017-02-02  7:37 ` Bug in regexp operator when warn_create_global is in effect Ronald Fischer
@ 2017-02-02  9:43   ` Peter Stephenson
  2017-02-02 22:55     ` Bart Schaefer
  2017-02-06 10:44     ` Ronald Fischer
  0 siblings, 2 replies; 10+ messages in thread
From: Peter Stephenson @ 2017-02-02  9:43 UTC (permalink / raw)
  To: zsh-workers

On Thu, 02 Feb 2017 08:37:16 +0100
Ronald Fischer <ynnor@mm.st> wrote:
> Consider the following program:
> 
>    #!/bin/zsh
>    function f {
>       [[ x =~ x ]]
>    }
>    setopt warn_create_global
>    f
> 
> When run by zsh 5.2 (x86_64-ubuntu-linux-gnu), I get the error messages:
> 
> f:1: scalar parameter MATCH created globally in function f
> f:1: numeric parameter MBEGIN created globally in function f
> f:1: numeric parameter MEND created globally in function f
> 
> While it is correct, that regexp matching sets, as side effect, the
> variables mentioned here, it doesn't, IMHO, make much sense that a zsh
> user, who not even *uses* these variables, receives these error
> messages.

Yes, you're right, the user doesn't even necessarily want them, which is
different from the case of the globbing flags in native zsh
expressions.  So probably best to turn the warnings off.

We don't yet have quite the full infrastructure for numerical
variables, annoyingly, but probably useful to add anyway...

pws

diff --git a/Src/Modules/regex.c b/Src/Modules/regex.c
index edb7234..d02769e 100644
--- a/Src/Modules/regex.c
+++ b/Src/Modules/regex.c
@@ -111,7 +111,7 @@ zcond_regex_match(char **a, int id)
 		*x = NULL;
 	    }
 	    if (isset(BASHREMATCH)) {
-		setaparam("BASH_REMATCH", arr);
+		assignaparam("BASH_REMATCH", arr, 0);
 	    } else {
 		zlong offs;
 		char *ptr;
@@ -119,7 +119,7 @@ zcond_regex_match(char **a, int id)
 
 		m = matches;
 		s = metafy(lhstr + m->rm_so, m->rm_eo - m->rm_so, META_DUP);
-		setsparam("MATCH", s);
+		assignsparam("MATCH", s, 0);
 		/*
 		 * Count the characters before the match.
 		 */
@@ -133,7 +133,7 @@ zcond_regex_match(char **a, int id)
 		    ptr += clen;
 		    leftlen -= clen;
 		}
-		setiparam("MBEGIN", offs + !isset(KSHARRAYS));
+		assigniparam("MBEGIN", offs + !isset(KSHARRAYS), 0);
 		/*
 		 * Add on the characters in the match.
 		 */
@@ -144,7 +144,7 @@ zcond_regex_match(char **a, int id)
 		    ptr += clen;
 		    leftlen -= clen;
 		}
-		setiparam("MEND", offs + !isset(KSHARRAYS) - 1);
+		assigniparam("MEND", offs + !isset(KSHARRAYS) - 1, 0);
 		if (nelem) {
 		    char **mbegin, **mend, **bptr, **eptr;
 		    bptr = mbegin = (char **)zalloc(sizeof(char *)*(nelem+1));
diff --git a/Src/params.c b/Src/params.c
index 20abe6a..19cbb1c 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -3192,11 +3192,12 @@ sethparam(char *s, char **val)
 
 /*
  * Set a generic shell number, floating point or integer.
+ * Option to warn on setting.
  */
 
 /**/
-Param
-setnparam(char *s, mnumber val)
+mod_export Param
+assignnparam(char *s, mnumber val, int flags)
 {
     struct value vbuf;
     Value v;
@@ -3248,15 +3249,41 @@ setnparam(char *s, mnumber val)
 	    unqueue_signals();
 	    return NULL;
 	}
-	check_warn_pm(v->pm, "numeric", !was_unset, 1);
+	if (flags & ASSPM_WARN)
+	    check_warn_pm(v->pm, "numeric", !was_unset, 1);
     } else {
-	check_warn_pm(v->pm, "numeric", 0, 1);
+	if (flags & ASSPM_WARN)
+	    check_warn_pm(v->pm, "numeric", 0, 1);
     }
     setnumvalue(v, val);
     unqueue_signals();
     return v->pm;
 }
 
+/*
+ * Set a generic shell number, floating point or integer.
+ * Warn on setting based on option.
+ */
+
+/**/
+mod_export Param
+setnparam(char *s, mnumber val)
+{
+    return assignnparam(s, val, ASSPM_WARN);
+}
+
+/* Simplified interface to assignnparam */
+
+/**/
+mod_export Param
+assigniparam(char *s, zlong val, int flags)
+{
+    mnumber mnval;
+    mnval.type = MN_INTEGER;
+    mnval.u.l = val;
+    return assignnparam(s, mnval, flags);
+}
+
 /* Simplified interface to setnparam */
 
 /**/
@@ -3266,7 +3293,7 @@ setiparam(char *s, zlong val)
     mnumber mnval;
     mnval.type = MN_INTEGER;
     mnval.u.l = val;
-    return setnparam(s, mnval);
+    return assignnparam(s, mnval, ASSPM_WARN);
 }
 
 /*


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Bug in regexp operator when warn_create_global is in effect
  2017-02-02  9:43   ` Peter Stephenson
@ 2017-02-02 22:55     ` Bart Schaefer
  2017-02-03  9:20       ` Peter Stephenson
  2017-02-06 10:44     ` Ronald Fischer
  1 sibling, 1 reply; 10+ messages in thread
From: Bart Schaefer @ 2017-02-02 22:55 UTC (permalink / raw)
  To: zsh-workers

On Feb 2,  9:43am, Peter Stephenson wrote:
}
} > While it is correct, that regexp matching sets, as side effect, the
} > variables mentioned here, it doesn't, IMHO, make much sense that a zsh
} > user, who not even *uses* these variables, receives these error
} > messages.
} 
} Yes, you're right, the user doesn't even necessarily want them
} [...].  So probably best to turn the warnings off.

Didn't we discuss this once beforeand decide exactly the opposite?

Yes, here:
    http://www.zsh.org/mla/workers//2015/msg03106.html

That seems to directly contradict what you just said/patched.


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Bug in regexp operator when warn_create_global is in effect
  2017-02-02 22:55     ` Bart Schaefer
@ 2017-02-03  9:20       ` Peter Stephenson
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Stephenson @ 2017-02-03  9:20 UTC (permalink / raw)
  To: zsh-workers

On Thu, 2 Feb 2017 14:55:27 -0800
Bart Schaefer <schaefer@brasslantern.com> wrote:

> On Feb 2,  9:43am, Peter Stephenson wrote:
> }
> } > While it is correct, that regexp matching sets, as side effect, the
> } > variables mentioned here, it doesn't, IMHO, make much sense that a zsh
> } > user, who not even *uses* these variables, receives these error
> } > messages.
> } 
> } Yes, you're right, the user doesn't even necessarily want them
> } [...].  So probably best to turn the warnings off.
> 
> Didn't we discuss this once beforeand decide exactly the opposite?
> 
> Yes, here:
>     http://www.zsh.org/mla/workers//2015/msg03106.html
> 
> That seems to directly contradict what you just said/patched.

That's a fair point to bring up, and I remember the discussion now you
point it out, but that appears to have been more general --- in
particular, I believe I was mostly thinking about cases where the user
would have done something explicitly causing the variable to be set as
a key part of what they were doing rather than as a side effect.  For
example, anything setting REPLY has been called to get a reply, and in
native zsh, match / MATCH etc. are triggered by globbing flags.

I refer the honourable gentleman to the closing remark I made to the
list on that occasion:

> If we need to make exceptions, I think they're more likely to be connected
> to specific instances of setting variables internally.

I think this can be considered one such case --- the user is doing a
basic regular expression where the result they want is the result of the
test, and they may not even be aware that variables are created.  As a
second possibly significant point, this is not zsh-specific syntax, it's
allowed in other recent shells where you wouldn't expect to have to
declare the variables.

I'm sure you can argue this the other way, though.

pws


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Bug in regexp operator when warn_create_global is in effect
  2017-02-02  9:43   ` Peter Stephenson
  2017-02-02 22:55     ` Bart Schaefer
@ 2017-02-06 10:44     ` Ronald Fischer
  2017-02-06 11:11       ` Peter Stephenson
  1 sibling, 1 reply; 10+ messages in thread
From: Ronald Fischer @ 2017-02-06 10:44 UTC (permalink / raw)
  To: Peter Stephenson, zsh-workers


> Yes, you're right, the user doesn't even necessarily want them, which is
> different from the case of the globbing flags in native zsh
> expressions.  So probably best to turn the warnings off.

I wouldn't consider this an optimal solution. This type of warning
proved to be extremely useful, and was catching already several spelling
errors in our own program.

Even worse, this new behaviour was not present in 5.1.1, and since we
are migrating a large zsh codebase from 5.1.1 to 5.2, we suddenly get
these warnings in several places.
Ronald


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Bug in regexp operator when warn_create_global is in effect
  2017-02-06 10:44     ` Ronald Fischer
@ 2017-02-06 11:11       ` Peter Stephenson
  2017-02-06 11:26         ` Ronald Fischer
  0 siblings, 1 reply; 10+ messages in thread
From: Peter Stephenson @ 2017-02-06 11:11 UTC (permalink / raw)
  To: Ronald Fischer; +Cc: zsh-workers

On Mon, 06 Feb 2017 11:44:09 +0100
Ronald Fischer <ynnor@mm.st> wrote:
> > Yes, you're right, the user doesn't even necessarily want them, which is
> > different from the case of the globbing flags in native zsh
> > expressions.  So probably best to turn the warnings off.
> 
> I wouldn't consider this an optimal solution. This type of warning
> proved to be extremely useful, and was catching already several spelling
> errors in our own program.

I'm not sure what you're referring to, but the change only turns off the
warnings for the case in question, i.e. regular expression matches,
where the use of the variables is hidden, the one you were complaining
about.  You were talking about creating the relevant variables even if
they were never used, but simply not warning when they are created by
the syntax in question should be equivalent and less invasive, I think.
(Those are "the warnings" I was talking about:  I wasn't explicit, which
may have caused confusion.)

Furthermore, creating MATCH etc. would suppress warnings in other cases
where zsh-specific syntax is used to request they be created, in
particular the globbing flag (#m), and from the above you appear to be
suggesting other cases should (ideally) not be suppressed.

If you're talking about other cases, if you could show exactly what's
triggering a warning, or failing to trigger it, I'll have a look.

pws


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Bug in regexp operator when warn_create_global is in effect
  2017-02-06 11:11       ` Peter Stephenson
@ 2017-02-06 11:26         ` Ronald Fischer
  2017-02-06 12:02           ` Peter Stephenson
  0 siblings, 1 reply; 10+ messages in thread
From: Ronald Fischer @ 2017-02-06 11:26 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-workers



On Mon, Feb 6, 2017, at 12:11, Peter Stephenson wrote:
> On Mon, 06 Feb 2017 11:44:09 +0100
> Ronald Fischer <ynnor@mm.st> wrote:
> > > Yes, you're right, the user doesn't even necessarily want them, which is
> > > different from the case of the globbing flags in native zsh
> > > expressions.  So probably best to turn the warnings off.
> > 
> > I wouldn't consider this an optimal solution. This type of warning
> > proved to be extremely useful, and was catching already several spelling
> > errors in our own program.
> 
> I'm not sure what you're referring to, but the change only turns off the
> warnings for the case in question, i.e. regular expression matches,
> where the use of the variables is hidden, the one you were complaining
> about.  

I think I misunderstood your comment here. I thought that you did not
want to change anything in zsh, but recommend that I simply turn off
warning about creating globals inside functions. This indeed would not
have been a good idea.

Basically, I want to be warned about globals which I explicitly create
by myself, but I don't want to be warned about globals which are created
implicitly by zsh (since I don't have any control about them.

> If you're talking about other cases, if you could show exactly what's
> triggering a warning, or failing to trigger it, I'll have a look.

The case is exactly the example program I've supplied: We get a warning
about a global variable being created, while this variable is not even
mentioned anywhere in the code.

About the suggestion in my original posting: What speaks against the
idea of creating all "implicit variables" as globals implicitly, when
the shell starts execution? That is, a program

    #!/bin/zsh
    source something
    foo bar

would be equivalent (that is, internally replaced) by

    #!/bin/zsh
    MATCH=
    source something
    foo bar

If you worry that MATCH could be an exported variable in the parent
shell (and hence must not be modified), it is trivial to include this
case as well.

Ronald


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Bug in regexp operator when warn_create_global is in effect
  2017-02-06 11:26         ` Ronald Fischer
@ 2017-02-06 12:02           ` Peter Stephenson
  2017-02-06 15:48             ` Ronald Fischer
  0 siblings, 1 reply; 10+ messages in thread
From: Peter Stephenson @ 2017-02-06 12:02 UTC (permalink / raw)
  To: zsh-workers

On Mon, 06 Feb 2017 12:26:37 +0100
Ronald Fischer <ynnor@mm.st> wrote:
> Basically, I want to be warned about globals which I explicitly create
> by myself, but I don't want to be warned about globals which are created
> implicitly by zsh (since I don't have any control about them.

You might want to look at the discussion Bart referred to in his
previous post,

http://www.zsh.org/mla/workers//2015/msg03106.html

but here's the summary.

The main point is to handle cases something like the following, where
although the variable creation is hidden it's explicitly requested by the
user:

fn() {
   [[ $1 = (#m)${~2} ]]
}

That (#m) in the pattern and the fact the pattern is in a function are
the only relevant facts here.  The (#m) is a request to cause MATCH,
MBEGIN and MEND to be set by the shell.  Because that's the purpose of
(#m), you want the warning so as to be able to decide whether those
variables are to be global or not and resolve between the two with a
local or typeset -g.

Your case is different because the use of the variables isn't requested
by special syntax, it's buried under standard regex syntax, so I've
fixed it for that one case.  I'm certainly interested in any more like
this you come up with.

> > If you're talking about other cases, if you could show exactly what's
> > triggering a warning, or failing to trigger it, I'll have a look.
> 
> The case is exactly the example program I've supplied: We get a warning
> about a global variable being created, while this variable is not even
> mentioned anywhere in the code.

That's fixed by my patch, as far as I can tell with no collateral
damage.  Please do report any further problems of this type so we can
discuss explicitly what's going on, which always makes things much
easier.

> About the suggestion in my original posting: What speaks against the
> idea of creating all "implicit variables" as globals implicitly, when
> the shell starts execution? That is, a program
> 
>     #!/bin/zsh
>     source something
>     foo bar
> 
> would be equivalent (that is, internally replaced) by
> 
>     #!/bin/zsh
>     MATCH=
>     source something
>     foo bar

Unless you're implying something further I haven't grapsed, that MATCH
variable is always and only cruft that's never actually providing a
useful value, and in some (as above) cases you might even want to guard
against it being global if it is created.  Also, it's not useful for any
purpose for anyone who isn't using WANRCREATEGLOBAL.  Tests to see if
the variable MATCH is set would become useless, as it always is set,
potentially breaking scripts.

(You won't know this, because it's new syntax, but we've just introduced
a new option WARN_NESTED_VAR that warns if you set a variable in an
enclosing scope, which you can turn on for specific functions if
needed.  Your trick doesn't fix that case, fixing the individual warning
does.  That option may not interest you anyway, as it's a bit more
invasive than WARN_CREATE_GLOBAL, but the problem is still there.)

I would hope there are better ways of fixing the problems related to the
warning itself, as I've done in this particular case, which is why I'd
like to see any further explicit examples in case there are any that
don't obviously fit one way or the other.

pws


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Bug in regexp operator when warn_create_global is in effect
  2017-02-06 12:02           ` Peter Stephenson
@ 2017-02-06 15:48             ` Ronald Fischer
  2017-02-06 16:04               ` Peter Stephenson
  0 siblings, 1 reply; 10+ messages in thread
From: Ronald Fischer @ 2017-02-06 15:48 UTC (permalink / raw)
  To: Peter Stephenson, zsh-workers

> The main point is to handle cases something like the following, where
> although the variable creation is hidden it's explicitly requested by the
> user:
> 
> fn() {
>    [[ $1 = (#m)${~2} ]]
> }
> 
> That (#m) in the pattern and the fact the pattern is in a function are
> the only relevant facts here.  The (#m) is a request to cause MATCH,
> MBEGIN and MEND to be set by the shell.  Because that's the purpose of
> (#m), you want the warning so as to be able to decide whether those
> variables are to be global or not and resolve between the two with a
> local or typeset -g.
> 
> Your case is different because the use of the variables isn't requested
> by special syntax, it's buried under standard regex syntax, so I've
> fixed it for that one case.  I'm certainly interested in any more like
> this you come up with.

Now I get it! Thanks for the explanation!

This (#m) example makes me think to the following problem (looks like an
opened can of worms): 

Clearly, a user who is aware to the global-vs-local topic will
conciously decide, whether he wants the M* variables local or global,
but no matter how he decides, it would be an insane decision if he
doesn't decide for the same scope on all three variables. For example,
it doesn't make sense to define MBEGIN as global and MATCH and MEND as
local. From the programmer's viewpoint, it would be more natural to
either decide on these three variables "as a group". Either all global
or all local. Currently, there is nothing which would enforce this
decision.

This now looks like a special case for (#m), but I wonder whether the
same wouldn't be true too for zsh modules, which also might create sets
of variables which belong together.

>From a programmer's viewpoint, a good concept (IMHO) would be that these
automatically created variables are always local, so if a function wants
to make a match globally visible, it would have to create its own global
variable for this. In the same way, it would perhaps make sense that
loop variables (in for-loop) are by default local, because this is the
usual way to use them. However, in both cases this might break existing
code, so it is perhaps not a real alternative. Seems that we have to
live with a compromise.

> That's fixed by my patch, as far as I can tell with no collateral
> damage. 

Thanks a lot, really. From which zsh version will this be available?

Ronald


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Bug in regexp operator when warn_create_global is in effect
  2017-02-06 15:48             ` Ronald Fischer
@ 2017-02-06 16:04               ` Peter Stephenson
  0 siblings, 0 replies; 10+ messages in thread
From: Peter Stephenson @ 2017-02-06 16:04 UTC (permalink / raw)
  To: Ronald Fischer; +Cc: zsh-workers

On Mon, 06 Feb 2017 16:48:10 +0100
Ronald Fischer <ynnor@mm.st> wrote:
> Now I get it! Thanks for the explanation!
> 
> This (#m) example makes me think to the following problem (looks like an
> opened can of worms): 
> 
> Clearly, a user who is aware to the global-vs-local topic will
> conciously decide, whether he wants the M* variables local or global,
> but no matter how he decides, it would be an insane decision if he
> doesn't decide for the same scope on all three variables. For example,
> it doesn't make sense to define MBEGIN as global and MATCH and MEND as
> local. From the programmer's viewpoint, it would be more natural to
> either decide on these three variables "as a group". Either all global
> or all local. Currently, there is nothing which would enforce this
> decision.

Yes, indeed.  We're right at the limit of what you can get from a single
option.  You could argue even the various cases of MATCH, REPLY,
etc. could have been a different option from the original
WARN_CREATE_GLOBAL --- it isn't basically because it still fits in with
what I originally thought the option was for, but I think your use is a
little different. Too late now.

The case of leaving one of the variables as a global and then having it
overridden in a function is what the new WARN_NESTED_VAR / functions -W
is about.  But that's arguably something of a sledgehammer:  that's why
we made it settable for only one function at a time as well as
glboally.  (That will also appear in 5.4 if you ever want to
investigate.)

> From a programmer's viewpoint, a good concept (IMHO) would be that these
> automatically created variables are always local, so if a function wants
> to make a match globally visible, it would have to create its own global
> variable for this. In the same way, it would perhaps make sense that
> loop variables (in for-loop) are by default local, because this is the
> usual way to use them. However, in both cases this might break existing
> code, so it is perhaps not a real alternative. Seems that we have to
> live with a compromise.

Yes, it's all rather a compromise.  Shell language is a bit of an
outlier in terms of modern scripting languages in many ways.

We actually recently rejected the notion of automatically making things
local as making scoping that bit too complicated, introducing too many
incompatibilities or possible hard to find glitches, etc., and I think
it's quite unlikely we'd go down that route as things stand.  (We
invented WARN_NESTED_VAR as a proxy.)  But that certainly doesn't mean
what we've got is perfect.

> > That's fixed by my patch, as far as I can tell with no collateral
> > damage. 
> 
> Thanks a lot, really. From which zsh version will this be available?

Will be in 5.4 --- but that's not currently imminent.  I'd like to
have quicker releases than we did last year, if possible, but it seems
the shell doesn't currently compile on at least one not-very-obscure
system.

pws


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-02-06 16:14 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20170202073801epcas4p3fa77b3bbe2794d2f574ac0319f13ab3f@epcas4p3.samsung.com>
2017-02-02  7:37 ` Bug in regexp operator when warn_create_global is in effect Ronald Fischer
2017-02-02  9:43   ` Peter Stephenson
2017-02-02 22:55     ` Bart Schaefer
2017-02-03  9:20       ` Peter Stephenson
2017-02-06 10:44     ` Ronald Fischer
2017-02-06 11:11       ` Peter Stephenson
2017-02-06 11:26         ` Ronald Fischer
2017-02-06 12:02           ` Peter Stephenson
2017-02-06 15:48             ` Ronald Fischer
2017-02-06 16:04               ` Peter Stephenson

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).