zsh-users
 help / color / mirror / code / Atom feed
* print builtin preceded by parameter assignment
@ 2019-04-10 12:55 ` Vincent Lefevre
  2019-04-10 13:14   ` Peter Stephenson
  0 siblings, 1 reply; 12+ messages in thread
From: Vincent Lefevre @ 2019-04-10 12:55 UTC (permalink / raw)
  To: zsh-users

It seems that the print builtin doesn't take into account a change
of the environment with a parameter assignment. For instance:

cventin% zsh -c 'TZ=UTC print -P "%D{%c}"'
2019-04-10T14:53:50 CEST
cventin% zsh -c 'export TZ=UTC; print -P "%D{%c}"'
2019-04-10T12:53:53 UTC

Is there any (undocumented?) reason or is this a bug?

I'm using zsh 5.7.1 under Debian unstable.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

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

* Re: print builtin preceded by parameter assignment
  2019-04-10 12:55 ` print builtin preceded by parameter assignment Vincent Lefevre
@ 2019-04-10 13:14   ` Peter Stephenson
  2019-04-10 14:11     ` Vincent Lefevre
  0 siblings, 1 reply; 12+ messages in thread
From: Peter Stephenson @ 2019-04-10 13:14 UTC (permalink / raw)
  To: zsh-users

On Wed, 2019-04-10 at 14:55 +0200, Vincent Lefevre wrote:
> It seems that the print builtin doesn't take into account a change
> of the environment with a parameter assignment. For instance:
> 
> cventin% zsh -c 'TZ=UTC print -P "%D{%c}"'
> 2019-04-10T14:53:50 CEST
> cventin% zsh -c 'export TZ=UTC; print -P "%D{%c}"'
> 2019-04-10T12:53:53 UTC
> 
> Is there any (undocumented?) reason or is this a bug?

It's certainly the case that such assignments only go into the
environment, and aren't processed within the shell.

I *think* this is standard behaviour:

http://pubs.opengroup.org/onlinepubs/9699919799/

2.9.1 specifies that unless the command is a special builtin utility,
the "current execution environment" is not affected by the assignment;
the value is simply exported.  I'd certainly assume the time zone seen
by % escapes is part of the current execution environment.  Neither
print (obvioussy) nor echo are special builtin utilities.

As this is a standard, I may simply have misread it.

pws


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

* Re: print builtin preceded by parameter assignment
  2019-04-10 13:14   ` Peter Stephenson
@ 2019-04-10 14:11     ` Vincent Lefevre
  2019-04-10 14:39       ` Peter Stephenson
  0 siblings, 1 reply; 12+ messages in thread
From: Vincent Lefevre @ 2019-04-10 14:11 UTC (permalink / raw)
  To: zsh-users

On 2019-04-10 14:14:13 +0100, Peter Stephenson wrote:
> On Wed, 2019-04-10 at 14:55 +0200, Vincent Lefevre wrote:
> > It seems that the print builtin doesn't take into account a change
> > of the environment with a parameter assignment. For instance:
> > 
> > cventin% zsh -c 'TZ=UTC print -P "%D{%c}"'
> > 2019-04-10T14:53:50 CEST
> > cventin% zsh -c 'export TZ=UTC; print -P "%D{%c}"'
> > 2019-04-10T12:53:53 UTC
> > 
> > Is there any (undocumented?) reason or is this a bug?
> 
> It's certainly the case that such assignments only go into the
> environment, and aren't processed within the shell.
> 
> I *think* this is standard behaviour:
> 
> http://pubs.opengroup.org/onlinepubs/9699919799/
> 
> 2.9.1 specifies that unless the command is a special builtin utility,
> the "current execution environment" is not affected by the assignment;
> the value is simply exported.  I'd certainly assume the time zone seen
> by % escapes is part of the current execution environment.  Neither
> print (obvioussy) nor echo are special builtin utilities.
> 
> As this is a standard, I may simply have misread it.

This is not how I interpret it (see below). But anyway, non-special
builtins are not in the scope of POSIX, unless you regard these
builtins as functions (in the sense, with a similar behavior), in
which case, the current behavior seems to be a bug.

POSIX distinguish 4 cases with a command name, and it depends on
which case you assume to apply to the "print" builtin.

1. If the command name is not a special built-in utility or function,
the variable assignments shall be exported for the execution environment
of the command [...]

In this case, the variable assignments should affect the output.

2. If the command name is a standard utility implemented as a function,
the effect of variable assignments shall be as if the utility was not
implemented as a function.

The "print" builtin is not a standard utility, so that this does not
apply (otherwise this is similar enough to cases 1 and 4).

3. If the command name is a special built-in utility, variable
assignments shall affect the current execution environment.

If you want to regard the "print" builtin as a special built-in
utility, the variable assignments should affect its output.

4. If the command name is a function that is not a standard utility
implemented as a function, variable assignments shall affect the
current execution environment during the execution of the function.

Again, in this case, if you regard the "print" builtin as similar
to some (opaque) function, the variable assignments should affect
its output.

As a summary, it is expected that in *any* case, variable assignments
affect the output.

When POSIX talks about the current execution environment is what
occurs around the execution of the command/function/... (e.g.
expansions and code run after the execution of the command).

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

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

* Re: print builtin preceded by parameter assignment
  2019-04-10 14:11     ` Vincent Lefevre
@ 2019-04-10 14:39       ` Peter Stephenson
  2019-04-10 17:25         ` Bart Schaefer
  2019-04-11 10:45         ` Vincent Lefevre
  0 siblings, 2 replies; 12+ messages in thread
From: Peter Stephenson @ 2019-04-10 14:39 UTC (permalink / raw)
  To: zsh-users

On Wed, 2019-04-10 at 16:11 +0200, Vincent Lefevre wrote:
> 1. If the command name is not a special built-in utility or function,
> the variable assignments shall be exported for the execution environment
> of the command [...]
> 
> In this case, the variable assignments should affect the output.

I see how you're interpreting this --- the "execution environment of the
command" is anything the command happens to do, not just what the
environment itself would show, while "the current execution
environment", which explicitly isn't affected by a bit you didn't quote
and which I assumed included "print" as it is part of the current
execution environment, to you is just what happens after the command
finishes.

In any case, I wasn't planning on changing this --- effectively adding a
full local variable behaviour when the intention of the syntax is to
export a parameter to the environment is a bit perverse.  If anyone else
thinks they can do it without major grief they're welcome to have a go
and we can see if the end justifies the means.  Often (but by no means
necessarily) this sort of thing breaks more than it fixes.

pws


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

* Re: print builtin preceded by parameter assignment
  2019-04-10 14:39       ` Peter Stephenson
@ 2019-04-10 17:25         ` Bart Schaefer
  2019-04-11 10:40           ` Vincent Lefevre
  2019-04-11 10:45         ` Vincent Lefevre
  1 sibling, 1 reply; 12+ messages in thread
From: Bart Schaefer @ 2019-04-10 17:25 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh Users

For what it's worth, Bash seems to (mostly) agree with the zsh
interpretation.  If I set HISTTIMEFORMAT to something containing %Z
and then run "TZ=UTC history" I get timestamps in the local timezone,
not in UTC.  If I first export TZ=UTC and then run history, I get
timestamps in UTC.

*However*, if I run "HISTTIMEFORMAT='%r ' history" the change takes
place for the builtin and I get the different format.  So it seems to
matter whether the variable itself is "known" to Bash, or something.

In neither case does the assignment persist in the shell after
"history" is done executing.

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

* Re: print builtin preceded by parameter assignment
  2019-04-10 17:25         ` Bart Schaefer
@ 2019-04-11 10:40           ` Vincent Lefevre
  2019-04-11 20:58             ` Bart Schaefer
  0 siblings, 1 reply; 12+ messages in thread
From: Vincent Lefevre @ 2019-04-11 10:40 UTC (permalink / raw)
  To: zsh-users

On 2019-04-10 10:25:18 -0700, Bart Schaefer wrote:
> For what it's worth, Bash seems to (mostly) agree with the zsh
> interpretation.  If I set HISTTIMEFORMAT to something containing %Z
> and then run "TZ=UTC history" I get timestamps in the local timezone,
> not in UTC.  If I first export TZ=UTC and then run history, I get
> timestamps in UTC.

Your test seems incorrect.

$ HISTTIMEFORMAT=%Z
$ history
    1  CESTps
[...]
$ TZ=UTC history
    1  UTCps
[...]

This is with:

GNU bash, version 5.0.3(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2019 Free Software Foundation, Inc.

Ditto with:

GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.

Adding the --posix option doesn't change the behavior related to
the output timezone.

> *However*, if I run "HISTTIMEFORMAT='%r ' history" the change takes
> place for the builtin and I get the different format.

Ditto here.

> So it seems to matter whether the variable itself is "known" to
> Bash, or something.

At least I get a consistent behavior. This suggests something
wrong with your test of TZ.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

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

* Re: print builtin preceded by parameter assignment
  2019-04-10 14:39       ` Peter Stephenson
  2019-04-10 17:25         ` Bart Schaefer
@ 2019-04-11 10:45         ` Vincent Lefevre
  1 sibling, 0 replies; 12+ messages in thread
From: Vincent Lefevre @ 2019-04-11 10:45 UTC (permalink / raw)
  To: zsh-users

On 2019-04-10 15:39:46 +0100, Peter Stephenson wrote:
> On Wed, 2019-04-10 at 16:11 +0200, Vincent Lefevre wrote:
> > 1. If the command name is not a special built-in utility or function,
> > the variable assignments shall be exported for the execution environment
> > of the command [...]
> > 
> > In this case, the variable assignments should affect the output.
> 
> I see how you're interpreting this --- the "execution environment of the
> command" is anything the command happens to do, not just what the
> environment itself would show, while "the current execution
> environment", which explicitly isn't affected by a bit you didn't quote
> and which I assumed included "print" as it is part of the current
> execution environment, to you is just what happens after the command
> finishes.

Yes, for instance, I would have assumed the following to be similar:

cventin% zsh -c 'TZ=UTC print -P "%D{%c}"'
2019-04-11T12:41:37 CEST
cventin% zsh -c 'p() { print -P "%D{%c}" } ; TZ=UTC p'
2019-04-11T10:41:41 UTC

I don't see any reason why the current execution environment would
have a different meaning in the first case.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

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

* Re: print builtin preceded by parameter assignment
  2019-04-11 10:40           ` Vincent Lefevre
@ 2019-04-11 20:58             ` Bart Schaefer
  2019-04-11 21:42               ` Bart Schaefer
  0 siblings, 1 reply; 12+ messages in thread
From: Bart Schaefer @ 2019-04-11 20:58 UTC (permalink / raw)
  To: Zsh Users

On Thu, Apr 11, 2019 at 3:42 AM Vincent Lefevre <vincent@vinc17.net> wrote:
>
> On 2019-04-10 10:25:18 -0700, Bart Schaefer wrote:
> > For what it's worth, Bash seems to (mostly) agree with the zsh
> > interpretation.  If I set HISTTIMEFORMAT to something containing %Z
> > and then run "TZ=UTC history" I get timestamps in the local timezone
>
> Your test seems incorrect.

My bash version is 3.2, so this changed in 4.something.

The actual takeaway here is that TZ has to be pushed into the actual
environ strings, not just set temporarily as a local to the shell, in
order for the system time libraries to apply it to strftime et al.
Most other variables used by shell builtins would not have this
property.

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

* Re: print builtin preceded by parameter assignment
  2019-04-11 20:58             ` Bart Schaefer
@ 2019-04-11 21:42               ` Bart Schaefer
  2019-04-24 12:31                 ` Vincent Lefevre
  0 siblings, 1 reply; 12+ messages in thread
From: Bart Schaefer @ 2019-04-11 21:42 UTC (permalink / raw)
  To: Zsh Users

On Thu, Apr 11, 2019 at 1:58 PM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> The actual takeaway here is that TZ has to be pushed into the actual
> environ strings, not just set temporarily as a local to the shell, in
> order for the system time libraries to apply it to strftime et al.

The trick is to mark TZ exported before you try to use it as a prefix
assignment.

% echo $+TZ
0
% export TZ
% echo $+TZ
1
% print -P "%D{%c %Z}"
Thu Apr 11 14:27:39 2019 PDT
% TZ=UTC print -P "%D{%c %Z}"
Thu Apr 11 21:27:58 2019 UTC

Here's a semi-related oddity -- once the timezone is changed, it does
not change back, even though the TZ variable is not set:

% echo $TZ

% date
Thu Apr 11 21:28:18 UTC 2019

Oops, the timezone remains UTC even though the variable is no longer
set.  This has to be a side-effect of calling localtime() in
promptexpand().  Explicitly resetting TZ fixes it:

% export TZ=PST8PDT
% date
Thu Apr 11 14:29:25 PDT 2019

Also, once TZ is both marked for export and has a valid value,
everything works the way Vincent expects:

% TZ=UTC print -P "%D{%c %Z}"
Thu Apr 11 21:29:36 2019 UTC
% date
Thu Apr 11 14:29:43 PDT 2019
%

So the "bug" if there is one is that variables that aren't marked for
export don't magically become exported when used before a builtin in a
prefix assignment.

As an aside, TZ is explicitly referenced and manipulated when using
zsh/datetime strftime builtin, so it might not suffer from any of
these problems.  I haven't tested it

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

* Re: print builtin preceded by parameter assignment
  2019-04-11 21:42               ` Bart Schaefer
@ 2019-04-24 12:31                 ` Vincent Lefevre
  2019-04-24 16:00                   ` Bart Schaefer
  0 siblings, 1 reply; 12+ messages in thread
From: Vincent Lefevre @ 2019-04-24 12:31 UTC (permalink / raw)
  To: zsh-users

On 2019-04-11 14:42:08 -0700, Bart Schaefer wrote:
> The trick is to mark TZ exported before you try to use it as a prefix
> assignment.
> 
> % echo $+TZ
> 0
> % export TZ
> % echo $+TZ
> 1
> % print -P "%D{%c %Z}"
> Thu Apr 11 14:27:39 2019 PDT
> % TZ=UTC print -P "%D{%c %Z}"
> Thu Apr 11 21:27:58 2019 UTC

This is even more confusing: the "export" status should not have
an effect in a variable assignment before a command (in particular,
a builtin).

Actually there is another inconsistency without the "export":

zira% echo $+TZ $+LC_ALL
0 0
zira% print -P "%D{%c %Z}"
Wed Apr 24 14:19:39 2019 CEST
zira% TZ=UTC0 LC_ALL=fr_FR.utf8 print -P "%D{%c %Z}"
mer. 24 avril 2019 14:19:50 CEST CEST

Following the (IMHO, invalid) justification for TZ not being taken
into account with a builtin, the LC_ALL assignment should have also
been ignored. But this is not the case.

Ditto for CDPATH:

zira% printenv CDPATH
zira% cd home
cd: no such file or directory: home
zira% CDPATH=/ cd home
/home

> Here's a semi-related oddity -- once the timezone is changed, it does
> not change back, even though the TZ variable is not set:
> 
> % echo $TZ
> 
> % date
> Thu Apr 11 21:28:18 UTC 2019
> 
> Oops, the timezone remains UTC even though the variable is no longer
> set.  This has to be a side-effect of calling localtime() in
> promptexpand().

This is even worse.

[...]
> So the "bug" if there is one is that variables that aren't marked for
> export don't magically become exported when used before a builtin in a
> prefix assignment.

There are several bugs (perhaps all related):

1. The fact that TZ remains exported with a value different
   from $TZ.

2. The fact that TZ and other variables (at least LC_ALL and CDPATH)
   are handled differently with a variable assignment before a
   builtin, when not exported.

3. The fact that for TZ, the "export" status has an effect on
   the value taken into account in a builtin.

IMHO, for (2), the best solution would be to fix (2) to follow
the behavior of LC_ALL/CDPATH/... (which would correspond to my
original request). And this would make (3) pointless.

-- 
Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/>
100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/>
Work: CR INRIA - computer arithmetic / AriC project (LIP, ENS-Lyon)

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

* Re: print builtin preceded by parameter assignment
  2019-04-24 12:31                 ` Vincent Lefevre
@ 2019-04-24 16:00                   ` Bart Schaefer
  2019-04-25 19:47                     ` Bart Schaefer
  0 siblings, 1 reply; 12+ messages in thread
From: Bart Schaefer @ 2019-04-24 16:00 UTC (permalink / raw)
  To: Zsh Users

On Wed, Apr 24, 2019 at 5:33 AM Vincent Lefevre <vincent@vinc17.net> wrote:
>
> There are several bugs (perhaps all related):
>
> 1. The fact that TZ remains exported with a value different
>    from $TZ.

This is not related (and is not actually the case).  TZ does not
remain exported.  What remains is that the settz() call has changed
the current timezone of the zsh process to be something that differs
from the value of the TZ environment variable.

>> 2. The fact that TZ and other variables (at least LC_ALL and CDPATH)
>    are handled differently with a variable assignment before a
>    builtin, when not exported.

This is also not really related.  CDPATH is not an environment string
in the first place, it's an internal variable used only by zsh; the
fact that it can be exported is irrelevant to the behavior.  The
difference with LC_ALL is that it is recognized as semantically
meaningful to the shell, so it has special code to invoke setlocale()
whenever it changes.  TZ is not specially handled in the same way.

> 3. The fact that for TZ, the "export" status has an effect on
>    the value taken into account in a builtin.

Underneath this comes down to a system library issue:  The library
behaves differently depending on whether settz() [or setlocale()] has
been called, and if it has not been, then it behaves differently
depending on whether the values are truly in the process environ
array.  Its questionable whether zsh can (or should) track and
special-case every environment variable that has such side-effects.

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

* Re: print builtin preceded by parameter assignment
  2019-04-24 16:00                   ` Bart Schaefer
@ 2019-04-25 19:47                     ` Bart Schaefer
  0 siblings, 0 replies; 12+ messages in thread
From: Bart Schaefer @ 2019-04-25 19:47 UTC (permalink / raw)
  To: Zsh Users

On Wed, Apr 24, 2019 at 9:00 AM Bart Schaefer <schaefer@brasslantern.com> wrote:
>
> This is not related (and is not actually the case).  TZ does not
> remain exported.  What remains is that the settz() call has changed
> the current timezone of the zsh process to be something that differs
> from the value of the TZ environment variable.
>
> difference with LC_ALL is that it is recognized as semantically
> meaningful to the shell, so it has special code to invoke setlocale()
> whenever it changes.  TZ is not specially handled in the same way.

If we want to simultaneously fix the former bug and also begin
handling TZ the way Vincent expects, we would have to introduce
get/set functions for TZ analogous to those for LC_*, so that settz()
is invoked on TZ value change the same way setlocale() is on LC_*
changes.  Further we would have to examine uses elsewhere of settz()
and localtime() [most notably in prompts and zsh/datetime] to be sure
that those either aren't needed, or that they correctly save/restore
the timezone if forcing one that differs from $TZ (or from the orginal
starting timezone when TZ is not set).

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

end of thread, other threads:[~2019-04-25 19:48 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CGME20190410125753epcas1p4052249a86c562165e1fe2a485d70e70b@epcas1p4.samsung.com>
2019-04-10 12:55 ` print builtin preceded by parameter assignment Vincent Lefevre
2019-04-10 13:14   ` Peter Stephenson
2019-04-10 14:11     ` Vincent Lefevre
2019-04-10 14:39       ` Peter Stephenson
2019-04-10 17:25         ` Bart Schaefer
2019-04-11 10:40           ` Vincent Lefevre
2019-04-11 20:58             ` Bart Schaefer
2019-04-11 21:42               ` Bart Schaefer
2019-04-24 12:31                 ` Vincent Lefevre
2019-04-24 16:00                   ` Bart Schaefer
2019-04-25 19:47                     ` Bart Schaefer
2019-04-11 10:45         ` Vincent Lefevre

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).