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

Re: sourcing a sh file in zsh



On 2009-01-16 at 21:00 -0800, Bart Schaefer wrote:
> On Jan 16,  7:59pm, Phil Pennock wrote:
> } On 2009-01-16 at 10:29 -0800, Bart Schaefer wrote:
> } > with the obvious meaning of "turn on sh emulation while sourcing" and
> } > would otherwise behave like "source".  Might need a variant that has
> } > the path-searching semantics of "." as well.
> } 
> } Isn't there a problem where a function is defined which assumes one set
> } of semantics and the reset afterwards changes the semantics?
> 
> The reset after what?  This hypothetical feature?  Well, since it's
> hypothetical, I'd have to say no, there isn't a problem, because if
> the feature ever ceases to be hypothetical it should be implemented
> so as to avoid that problem.

Okay, and that raises the issue of reset and options from outside a
function needing to be retained as part of the function definition.

> I think I begin to understand what you mean, but I think it's misguided.
> There's no way for a function that's stored in script form as a file,
> and then later sourced or autoloaded, to keep track of what options
> were *intended* to be in effect at the time the file was stored to the
> disk.  It can only know what options were in effect at the time that
> the "source" command was executed, which doesn't solve the problem.
> 
> The closest you could get would be to add an option to zcompile to
> have it prepend the compiled function definition with an appropriate 
> setopts command.  This is already partly done by zcompile for the
> special case of KSH_AUTOLOAD.
> 
> I see from your example that you suggest hacking this up semi-manually
> by defining one function within another so that the outer function can
> establish the option settings that the inner one should remember, but
> that's only minimally helpful to the function writer and still doesn't
> solve the original problem of variable scoping.

The example in my notes is probably not the best; it's based on an
assumption that loading external non-zsh files is best done using a
function which sets the options wanted and sources, to restore the state
needed afterwards, but a zsource would be equivalent.

The problem I have is some utility libraries which are written with bash
as an assumption and then justified to the zsh-users with "hey, they
work with zsh too" because they, oh, setopt sh_word_split.  I don't want
my normal shell contaminated with that garbage -- I like zsh's
behaviour.

The idea is basically just "set this option and functions have an
implicit emulate at the start which sets the options in effect at the
time the function was defined", to let me source utility libraries and
have sh_word_split turned on for them (and probably ksh_arrays too)
without having it effect everything else I do in the shell.  The
front-end interface file, which sources everything else and which has
shell-specific shims to "handle" zsh can then have a zsh version-check
to just instead catch the value of the options, setopt inherit_options
and the others, and then restore options after it's done pulling in the
other files.

I can easily get updates made to the interface, but there's no way that
shell-specific stuff will get into every function defined across all the
other files -- #ifdef littering is bad, in any language.

So, the problem is probably my lack of understanding of various areas of
internals I haven't previously touched; my rought plan is:

 * use copies of opts, which can be memcpy'd around (since it's a static
   variable and making it a variable pointer might be more intrusive;
   wrap it in an API and this can be changed if it's easier to make opts
   a pointer which can be moved)
 * minimally, when inherit_options is in effect, bar changes to
   restricted, interactive, privileged, etc
 * setopt inherit_options creates a copy of opts; either:
   (a) this is read-only, no options changed within inherit scope, so
       set things up carefully first;
   (b) all functions defined within the scope of one instance of setting
       inherit_options share a unified option space and changes in one
       affect all others
 * At time of function call, see if crossing a boundary between values
   of inherit_options; if so, put the pointer to the current opts into a
   new item in struct funcstack; when unwinding stack, if the
   restoreopts item is non-NULL, restore it.

The problem is how to decide if a function needs a new option; I haven't
looked too closely but I believe that functions are invoked from each
other directly via the Eprog code, rather than dispatch through the
shfunctab shfunc entries, so it's not viable to go via extending shfunc
(pity).

So I'm thinking an Eprog WC_OPTSPACE instruction which can be inserted
at some point arounf execfuncdef() time, which is stored with a value
which points to the opts value to be put into effect and which, when
encountered, adjusts the current funcstack entry to hold the current
opts before replacing opts with the one referenced in the Eprog.

Okay, how many fundamental misunderstandings on my part have I just
exposed?

-Phil



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