Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Issue with VAR=foo cmd where VAR is a named reference



Hmm, there's a complication here where you have to consider that (per
POSIX) some builtin commands preserve assignment to prefix environment
strings and some do not.  I don't immediately recall which category
"typeset" falls into.

I didn't know about that but the code to save and restore the assigned parameters is indeed conditional. If POSIXBUILTINS is enabled, typeset preserves the assignments:

% setopt POSIXBUILTINS; var=foo; var=bar typeset -p var; typeset -p var
typeset var=bar
typeset var=bar

> Exporting named references is in principle possible

I think that would be a bad choice.  For security reasons it should
not be possible to import a named reference, and other programs would
have no idea what to do with an environment instrumented by zsh for
the purpose.

I don't mean that it should be possible to export named references as something special that would be recognized as a named reference by a Zsh shell. I just mean that tagging a named reference R with -x could have for effect to augment the environment with the key value pair R=$R (if R refers to a non-array variable):

% typeset var=foo
% typeset -nx ref=var
% printenv | grep ref=
ref=var
% zsh -c 'typeset -p ref'
export ref=var

In principle, this is trivial. In practice, it's difficult because the environment is precomputed. Each time an exported scalar is updated, its associated key value pair is updated in the precomputed environment. For exported named references, you would have to go through the whole parameter table each time a scalar is updated just to find whether there are exported named references that refer to it and update their associated key value pairs in the precomputed environment. That would be prohibitively expensive.

> In other words, VAR=foo cmd, runs cmd with a parameter table where VAR's value has been temporarily changed to foo. If VAR happens to be a named reference, then it's the value of its referred variable that is changed.

I'm undecided about that.  It could be argued that
  VAR=foo command
should behave like
  () { local -x VAR=foo; command }
That is, VAR in the environment is entirely distinct from VAR in the
calling shell.  The difficult exception is the builtins that are
supposed to preserve assignment.  I suppose ksh behavior would be
worthwhile to investigate.

That's not unreasonable and it would make things pretty simple but I fear that it's not compatible with the current implementations; chances are that it would break existing scripts. Here is what the current implementation more or less does for VAR=foo cmd:

# Save the state of the variable referred by VAR
typeset -x VAR  # For named references, the -x applies to the referred variable
VAR=foo
cmd
# Restore the state of the variable referred by VAR

One difficulty (to switch to your proposal) is that the current implementation preserves the type of the variable. The following exports the value "7", not "3+4" (ksh does the same):

% typeset -i VAR=2; VAR=3+4 printenv VAR; typeset -p VAR
7
typeset -i VAR=2

Another difficulty is that assignments can use += (this too works the same in ksh)

% typeset -i VAR=2; VAR+=3 printenv VAR; typeset -p VAR
5
typeset -i VAR=2


It's even possible to assign slices

% fun() { typeset -p VAR }; typeset VAR=1234567; VAR[2,6]=abc fun; typeset -p VAR
typeset -g VAR=1abc7
typeset VAR=1abc7

But strangely that only works for functions and builtins and here the variable isn't restored to its previous state.

I have personally written scripts that rely on the fact that -i is preserved and that += works. Switching to the equivalent of a local variable would break these. No big deal for me but chances are that other people also made use of these features.

If we keep the current implementation, then it's pretty much unavoidable that REF=foo cmd updates the referred variable. We can just avoid exporting the referred variable.

Philippe



Messages sorted by: Reverse Date, Date, Thread, Author