zsh-workers
 help / color / mirror / code / Atom feed
* problem redeclaring path variable (ksh incompatibility)
@ 2005-03-17 14:31 Michael Wardle
  2005-03-17 16:50 ` Bart Schaefer
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Wardle @ 2005-03-17 14:31 UTC (permalink / raw)
  To: zsh-workers

Hi

I have a script that uses the identifier "path" local to a function.  It 
works as intended in bash and all the versions of ksh I've tried it on, 
but not in zsh, which gives an error message similar to this:
addpath:typeset:6: path: can't assign initial value for array

It turns out that neither "typeset path=" nor "typeset path=value" 
create a local scalar, which doesn't meet my expectations.  Strangely, 
however, "typeset path" does.

It also came as a bit of a surprise to me that "path" should be declared 
at all when zsh is emulating sh or ksh, but I don't see a good reason to 
remove that.

A test case follows in case you will consider investigating this problem 
and modifying zsh to act as bash does:
----------
#!/bin/zsh -p
# test case for zsh dynamic scoping of "path" variable
# Michael Wardle <michael@endbracket.net>
# invoked using -p to ignore user rc files

[ -n "$ZSH_VERSION" ] && emulate ksh    # arrays are 0 indexed, etc.
set -e                                  # exit on error

func()
{
         # create a dynamically scoped variable in function scope
         # the identifier exists at global scope as an array but is
         # redeclared here as a scalar
         #typeset path                   # this works
         typeset path="local0"           # this doesn't work
         path="local0"
         path="$path local1"
         echo "Inside function, values are:"
         set -- $path
         for elem
         do
                 echo "$elem"
         done
}

# create a dynamically scoped variable in global scope
typeset -a path
#export path            # path being exported doesn't matter
path[0]=global0
path[1]=global1
# display the globally scoped values
echo "Outside function, values are:"
set -- ${path[@]}
for elem
do
         echo "$elem"
done

func

# test that the globally scoped values are restored
echo "Outside function, values are:"
set -- ${path[@]}
for elem
do
         echo "$elem"
done
----------


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

* Re: problem redeclaring path variable (ksh incompatibility)
  2005-03-17 14:31 problem redeclaring path variable (ksh incompatibility) Michael Wardle
@ 2005-03-17 16:50 ` Bart Schaefer
  2005-03-17 17:28   ` Bart Schaefer
                     ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Bart Schaefer @ 2005-03-17 16:50 UTC (permalink / raw)
  To: Michael Wardle, zsh-workers

On Mar 18,  1:31am, Michael Wardle wrote:
} 
} I have a script that uses the identifier "path" local to a function.  It 
} works as intended in bash and all the versions of ksh I've tried it on, 
} but not in zsh, which gives an error message similar to this:
} addpath:typeset:6: path: can't assign initial value for array

Zsh does not fully emulate the POSIX shell unless it is invoked under the
name "sh".  The "emulate" command is not sufficient; it only changes the
setopts, not the set of special variables etc. that are predeclared at
startup time.  Hence the "path" variable exists and is special and may
only be overridden locally to a function by using "typeset -h path=...".

Try running your test script with ARGV0=sh in the environment and note
the difference in behavior.
 
} It turns out that neither "typeset path=" nor "typeset path=value" 
} create a local scalar, which doesn't meet my expectations.  Strangely, 
} however, "typeset path" does.

No, it doesn't.  Nowhere in your test script is $path a scalar.

zsh% func() { emulate ksh; typeset path ; path=scalar ; typeset path }
zsh% func
path=(scalar)
zsh% 

If we were going to attempt to change this, the right way would be to add
a new option, perhaps called LOCAL_SPECIALS, which would be on by default.
"emulate sh" et al. would unset this option.  When NO_LOCAL_SPECIALS, the
typeset builtin would behave as if the -h option were always present.

Other, less desirable approaches might be to tie this behavior to the
POSIX_BUILTINS or KSH_TYPESET options.  Possibly it should be tied to
KSH_TYPESET even if LOCAL_SPECIALS is added.


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

* Re: problem redeclaring path variable (ksh incompatibility)
  2005-03-17 16:50 ` Bart Schaefer
@ 2005-03-17 17:28   ` Bart Schaefer
  2005-03-17 21:42   ` Michael Wardle
  2005-03-18 10:52   ` Peter Stephenson
  2 siblings, 0 replies; 6+ messages in thread
From: Bart Schaefer @ 2005-03-17 17:28 UTC (permalink / raw)
  To: zsh-workers

On Mar 17,  4:50pm, Bart Schaefer wrote:
}
} If we were going to attempt to change this, the right way would be to add
} a new option, perhaps called LOCAL_SPECIALS, which would be on by default.
} "emulate sh" et al. would unset this option.  When NO_LOCAL_SPECIALS, the
} typeset builtin would behave as if the -h option were always present.
} 
} Other, less desirable approaches might be to tie this behavior to the
} POSIX_BUILTINS or KSH_TYPESET options.  Possibly it should be tied to
} KSH_TYPESET even if LOCAL_SPECIALS is added.

Here's a short patch that illustrates how this would work.  With this
patch applied, Michael's function works as he expects, and "typeset +h"
can be used to force a special to remain locally special.

Index: builtin.c
===================================================================
RCS file: /extra/cvsroot/zsh/zsh-4.0/Src/builtin.c,v
retrieving revision 1.30
diff -c -r1.30 builtin.c
--- builtin.c	18 Feb 2005 17:05:15 -0000	1.30
+++ builtin.c	17 Mar 2005 17:23:35 -0000
@@ -2236,6 +2236,9 @@
     if (on & PM_TIED)
 	off |= PM_INTEGER | PM_EFLOAT | PM_FFLOAT | PM_ARRAY | PM_HASHED;
 
+    if (isset(KSHTYPESET))
+	on |= PM_HIDE;
+
     on &= ~off;
 
     queue_signals();


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

* Re: problem redeclaring path variable (ksh incompatibility)
  2005-03-17 16:50 ` Bart Schaefer
  2005-03-17 17:28   ` Bart Schaefer
@ 2005-03-17 21:42   ` Michael Wardle
  2005-03-18  2:42     ` Bart Schaefer
  2005-03-18 10:52   ` Peter Stephenson
  2 siblings, 1 reply; 6+ messages in thread
From: Michael Wardle @ 2005-03-17 21:42 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: zsh-workers

Hi Bart

Thanks for your reply.

> Try running your test script with ARGV0=sh in the environment and note
> the difference in behavior.

It didn't appear to make any difference.  Are you sure this hides $path, 
or are you just suggesting this should be the normal way to invoke zsh 
any time I want it to conform closely to POSIX shell?

In any case, thanks for pointing out that feature.  I discovered this 
difference when asking zsh to read my general POSIX/Korn shell .shrc, so 
it is clear I should enable any sh/ksh compliance features before doing 
so.  I'll definitely investigate it some more.

> } It turns out that neither "typeset path=" nor "typeset path=value" 
> } create a local scalar, which doesn't meet my expectations.  Strangely, 
> } however, "typeset path" does.
> 
> No, it doesn't.  Nowhere in your test script is $path a scalar.

I had assumed it was since subsequent attempts to assign scalar (string) 
values to it succeed, and its global value is restored outside of the 
function.

So this works:
typeset path
path=
path="scalar"

But this doesn't:
typeset path=
path="scalar"

And neither does this:
typeset path=""
path="scalar"

> zsh% func() { emulate ksh; typeset path ; path=scalar ; typeset path }
> zsh% func
> path=(scalar)

Assuming a -m flag to the final typeset, this certainly verifies what 
you said.

Thanks


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

* Re: problem redeclaring path variable (ksh incompatibility)
  2005-03-17 21:42   ` Michael Wardle
@ 2005-03-18  2:42     ` Bart Schaefer
  0 siblings, 0 replies; 6+ messages in thread
From: Bart Schaefer @ 2005-03-18  2:42 UTC (permalink / raw)
  To: Michael Wardle; +Cc: zsh-workers

On Mar 18,  8:42am, Michael Wardle wrote:
} Subject: Re: problem redeclaring path variable (ksh incompatibility)
}
} > Try running your test script with ARGV0=sh in the environment and note
} > the difference in behavior.
} 
} It didn't appear to make any difference.

Er, I was assuming, because you were posting to a zsh mailing list, that
your usual shell was zsh, which is possibly a bad assumption.  That is,
ARGV0 is magic to zsh -- not to the new zsh being started up, but to the
currently running zsh that is printing your PS1 prompt.  If your login
shell is bash or ksh, the ARGV0=sh isn't going to make any difference.

So, first start an interactive zsh, and then from the prompt of that,
run "ARGV0=sh zsh -p yourtestscript", and NOT "ARGV0=sh yourtestscript".

Or, do "ln -s `which zsh` /tmp/sh" and then "/tmp/sh -p yourtestscript".

} Are you sure this hides $path

It causes it never to become set in the first place.

} or are you just suggesting this should be the normal way to invoke zsh 
} any time I want it to conform closely to POSIX shell?

If you want zsh to conform closely to the POSIX shell you have to make a
link to it whose pathname ends in "sh" (actually any string starting with
the letter "s" other than "su" will work) and run it via that link.  The
trick with ARGV0 is a zsh-ism that simulates having done so.

} So this works:
} typeset path
} path=
} path="scalar"

This declares a local path, but it inherits the special features of the
global path.  It then makes it empty (redundant), and finally makes it
a single-element array.

} But this doesn't:
} typeset path=
} path="scalar"

It doesn't work because "typeset path=" fails *entirely* when it prints
the "can't assign initial value" error message; consequently you have
not succeeded in declaring "path" to be local, and the assigment affects
the global.

} And neither does this:
} typeset path=""
} path="scalar"

Same problem.

} > zsh% func() { emulate ksh; typeset path ; path=scalar ; typeset path }
} > zsh% func
} > path=(scalar)
} 
} Assuming a -m flag to the final typeset, this certainly verifies what 
} you said.

Right, I forgot the -m is required in 4.2.  I tried it in 4.0, in which
older version "emulate ksh" does not imply "setopt TYPESET_SILENT".


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

* Re: problem redeclaring path variable (ksh incompatibility)
  2005-03-17 16:50 ` Bart Schaefer
  2005-03-17 17:28   ` Bart Schaefer
  2005-03-17 21:42   ` Michael Wardle
@ 2005-03-18 10:52   ` Peter Stephenson
  2 siblings, 0 replies; 6+ messages in thread
From: Peter Stephenson @ 2005-03-18 10:52 UTC (permalink / raw)
  To: Michael Wardle, zsh-workers

Bart Schaefer wrote:
> Hence the "path" variable exists and is special and may
> only be overridden locally to a function by using "typeset -h path=...".

Or you can run

typeset -h path

on the existing path variable in the main shell, e.g. at startup.  Then
you don't have to alter the function.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

**********************************************************************


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

end of thread, other threads:[~2005-03-18 10:52 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-17 14:31 problem redeclaring path variable (ksh incompatibility) Michael Wardle
2005-03-17 16:50 ` Bart Schaefer
2005-03-17 17:28   ` Bart Schaefer
2005-03-17 21:42   ` Michael Wardle
2005-03-18  2:42     ` Bart Schaefer
2005-03-18 10:52   ` 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).