From cf92384eac7c961d96a9bf3bde3df8f8427b45bc Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Thu, 13 Apr 2000 14:22:47 +0000 Subject: 10738: pws: local parameters can be exported --- ChangeLog | 7 ++++++ Doc/Zsh/builtins.yo | 15 +++++------ Doc/Zsh/params.yo | 18 ++++++-------- Src/builtin.c | 26 ++++++++------------ Src/params.c | 71 ++++++++++++++++++++++++++++++++++++++--------------- 5 files changed, 84 insertions(+), 53 deletions(-) diff --git a/ChangeLog b/ChangeLog index d65f3b160..2a9133ef3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2000-04-13 Peter Stephenson + + * 10738: Doc/Zsh/builtins.yo, Doc/Zsh/params.yo, Src/builtin.c, + Src/params.c: local parameters can be exported; typeset +g -x + and local -x work in a natural way; currently typeset -g still + behaves like typeset -gx. + 2000-04-13 Sven Wischnowsky * 10733: Completion/Builtins/_pids, Completion/User/_killall, diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo index cb7372cc5..0eadbc596 100644 --- a/Doc/Zsh/builtins.yo +++ b/Doc/Zsh/builtins.yo @@ -595,9 +595,10 @@ sitem([var(mm)tt(:)]var(ss))(minutes and seconds) endsitem() ) findex(local) -item(tt(local) [ {tt(PLUS())|tt(-)}tt(AEFLRUZahilrtu) [var(n)]] [ var(name)[tt(=)var(value)] ] ...)( -Same as tt(typeset), except that the options tt(-g), tt(-x) and -tt(-f) are not permitted. +item(tt(local) [ {tt(PLUS())|tt(-)}tt(AEFLRUZahilrtux) [var(n)]] [ var(name)[tt(=)var(value)] ] ...)( +Same as tt(typeset), except that the options tt(-g), and +tt(-f) are not permitted. In this case the tt(-x) option does not force +the use of tt(-g), i.e. exported variables will be local to functions. ) findex(log) vindex(watch, use of) @@ -1003,9 +1004,7 @@ var(name) (even those that already exist), and is unset again when the function completes. See ifzman(`Local Parameters' in zmanref(zshparam))\ ifnzman(noderef(Local Parameters))\ -. Local parameters are not exported unless tt(ALL_EXPORT) is set, in -which case the parameter is exported em(only) when var(name) does not -already exist. The same rules apply to special shell parameters, which +. The same rules apply to special shell parameters, which retain their special attributes when made local. For each var(name)tt(=)var(value) assignment, the parameter @@ -1161,7 +1160,9 @@ This flag has a different meaning when used with tt(-f); see above. ) item(tt(-x))( Mark for automatic export to the environment of subsequently -executed commands. +executed commands. Currently this implies the option tt(-g), unless tt(+g) +is also explicitly given, in other words the parameter is not made local to +the enclosing function. This is for compatibility with other shells. ) enditem() ) diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo index c6571f38f..ac90d095d 100644 --- a/Doc/Zsh/params.yo +++ b/Doc/Zsh/params.yo @@ -215,21 +215,19 @@ any outer parameter of the same name remains hidden. Special parameters may also be made local; they retain their special attributes unless either the existing or the newly-created parameter -has the tt(-h) (hide) attribute. This may have unexpected effects. -Firstly, there is no default value, so if there is no assigment at the +has the tt(-h) (hide) attribute. This may have unexpected effects: +there is no default value, so if there is no assigment at the point the variable is made local, it will be set to an empty value (or zero -in the case of integers). Secondly, special parameters which are made -local will not be exported (as with other parameters), so that the global -value of the parameter remains present in the environment if it is already -there. This should be particularly noted in the case of tt(PATH): the -shell will use the local version of tt(PATH) for finding programmes, but -programmes using the shell's environment will inherit the global version. +in the case of integers). The following: example(typeset PATH=/new/directory:$PATH) -is valid for temporarily allowing the shell to find the programs in -tt(/new/directory) inside a function. +is valid for temporarily allowing the shell or programmes called from it to +find the programs in tt(/new/directory) inside a function. + +Note that the restriction in older versions of zsh that local parameters +were never exported has been removed. texinode(Parameters Set By The Shell)(Parameters Used By The Shell)(Local Parameters)(Parameters) sect(Parameters Set By The Shell) diff --git a/Src/builtin.c b/Src/builtin.c index 6cb03b3f5..f18e956e8 100644 --- a/Src/builtin.c +++ b/Src/builtin.c @@ -79,7 +79,7 @@ static struct builtin builtins[] = BUILTIN("jobs", 0, bin_fg, 0, -1, BIN_JOBS, "dlpZrs", NULL), BUILTIN("kill", 0, bin_kill, 0, -1, 0, NULL, NULL), BUILTIN("let", 0, bin_let, 1, -1, 0, NULL, NULL), - BUILTIN("local", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AEFLRTUZahilrtu", NULL), + BUILTIN("local", BINF_TYPEOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AEFLRTUZahilrtux", NULL), BUILTIN("log", 0, bin_log, 0, 0, 0, NULL, NULL), BUILTIN("logout", 0, bin_break, 0, 1, BIN_LOGOUT, NULL, NULL), @@ -644,14 +644,12 @@ set_pwd_env(void) setsparam("OLDPWD", ztrdup(oldpwd)); pm = (Param) paramtab->getnode(paramtab, "PWD"); - if (!(pm->flags & PM_EXPORTED) && - (!pm->level || (isset(ALLEXPORT) && !pm->old))) { + if (!(pm->flags & PM_EXPORTED)) { pm->flags |= PM_EXPORTED; pm->env = addenv("PWD", pwd, pm->flags); } pm = (Param) paramtab->getnode(paramtab, "OLDPWD"); - if (!(pm->flags & PM_EXPORTED) && - (!pm->level || (isset(ALLEXPORT) && !pm->old))) { + if (!(pm->flags & PM_EXPORTED)) { pm->flags |= PM_EXPORTED; pm->env = addenv("OLDPWD", oldpwd, pm->flags); } @@ -1589,7 +1587,6 @@ typeset_single(char *cname, char *pname, Param pm, int func, } /* - * According to the manual, local parameters don't get exported. * A parameter will be local if * 1. we are re-using an existing local parameter * or @@ -1598,10 +1595,6 @@ typeset_single(char *cname, char *pname, Param pm, int func, * or * ii. we are creating a new local parameter */ - if ((usepm && pm->level) || - (!usepm && (pm || (locallevel && (on & PM_LOCAL))))) - on &= ~PM_EXPORTED; - if (usepm) { on &= ~PM_LOCAL; if (!on && !roff && !value) { @@ -1630,9 +1623,7 @@ typeset_single(char *cname, char *pname, Param pm, int func, if (pm->flags & PM_EXPORTED) { if (!(pm->flags & PM_UNSET) && !pm->env && !value) pm->env = addenv(pname, getsparam(pname), pm->flags); - } else if (pm->env && - (!pm->level || (isset(ALLEXPORT) && !pm->old && - !(pm->flags & PM_HASHELEM)))) { + } else if (pm->env && !(pm->flags & PM_HASHELEM)) { delenv(pm->env); zsfree(pm->env); pm->env = NULL; @@ -1708,7 +1699,11 @@ typeset_single(char *cname, char *pname, Param pm, int func, tpm->old = pm->old; tpm->level = pm->level; tpm->ct = pm->ct; - tpm->env = pm->env; + if (pm->env) { + delenv(pm->env); + zsfree(pm->env); + } + tpm->env = pm->env = NULL; pm->old = tpm; /* @@ -1725,7 +1720,6 @@ typeset_single(char *cname, char *pname, Param pm, int func, pm->ct = auxlen; else pm->ct = 0; - pm->env = NULL; } else { /* * Create a new node for a parameter with the flags in `on' minus the @@ -1856,7 +1850,7 @@ bin_typeset(char *name, char **argv, char *ops, int func) return 0; } - if (!ops['g'] && !ops['x']) + if ((!ops['g'] && !ops['x']) || ops['g'] == 2 || *name == 'l') on |= PM_LOCAL; if (on & PM_TIED) { diff --git a/Src/params.c b/Src/params.c index 3179fc6a7..6a9dfe588 100644 --- a/Src/params.c +++ b/Src/params.c @@ -643,13 +643,21 @@ createparam(char *name, int flags) } else { pm = (Param) zcalloc(sizeof *pm); if ((pm->old = oldpm)) { - /* needed to avoid freeing oldpm */ + /* + * needed to avoid freeing oldpm, but we do take it + * out of the environment when it's hidden. + */ + if (oldpm->env) { + delenv(oldpm->env); + zsfree(oldpm->env); + oldpm->env = NULL; + } paramtab->removenode(paramtab, name); } paramtab->addnode(paramtab, ztrdup(name), pm); } - if (isset(ALLEXPORT) && !oldpm && !(flags & PM_HASHELEM)) + if (isset(ALLEXPORT) && !(flags & PM_HASHELEM)) flags |= PM_EXPORTED; } else { pm = (Param) zhalloc(sizeof *pm); @@ -1445,12 +1453,31 @@ getnumvalue(Value v) return mn; } +/**/ +void +export_param(Param pm) +{ + char buf[(sizeof(zlong) * 8) + 4], *val; + + if (PM_TYPE(pm->flags) == PM_INTEGER) + convbase(val = buf, pm->gets.ifn(pm), pm->ct); + else if (pm->flags & (PM_EFLOAT|PM_FFLOAT)) + val = convfloat(pm->gets.ffn(pm), pm->ct, + pm->flags, NULL); + else + val = pm->gets.cfn(pm); + if (pm->env) + pm->env = replenv(pm->env, val, pm->flags); + else { + pm->flags |= PM_EXPORTED; + pm->env = addenv(pm->nam, val, pm->flags); + } +} + /**/ mod_export void setstrvalue(Value v, char *val) { - char buf[(sizeof(zlong) * 8) + 4]; - if (v->pm->flags & PM_READONLY) { zerr("read-only variable: %s", v->pm->nam, 0); zsfree(val); @@ -1523,22 +1550,10 @@ setstrvalue(Value v, char *val) break; } if ((!v->pm->env && !(v->pm->flags & PM_EXPORTED) && - !(isset(ALLEXPORT) && !v->pm->old && !(v->pm->flags & PM_HASHELEM))) || + !(isset(ALLEXPORT) && !(v->pm->flags & PM_HASHELEM))) || (v->pm->flags & PM_ARRAY) || v->pm->ename) return; - if (PM_TYPE(v->pm->flags) == PM_INTEGER) - convbase(val = buf, v->pm->gets.ifn(v->pm), v->pm->ct); - else if (v->pm->flags & (PM_EFLOAT|PM_FFLOAT)) - val = convfloat(v->pm->gets.ffn(v->pm), v->pm->ct, - v->pm->flags, NULL); - else - val = v->pm->gets.cfn(v->pm); - if (v->pm->env) - v->pm->env = replenv(v->pm->env, val, v->pm->flags); - else { - v->pm->flags |= PM_EXPORTED; - v->pm->env = addenv(v->pm->nam, val, v->pm->flags); - } + export_param(v->pm); } /**/ @@ -1969,6 +1984,15 @@ unsetparam_pm(Param pm, int altflag, int exp) if ((PM_TYPE(oldpm->flags) == PM_SCALAR) && oldpm->sets.cfn == strsetfn) adduserdir(oldpm->nam, oldpm->u.str, 0, 0); + if (oldpm->flags & PM_EXPORTED) { + /* + * Re-export the old value which we removed in typeset_single(). + * I don't think we need to test for ALL_EXPORT here, since if + * it was used to export the parameter originally the parmeter + * should still have the PM_EXPORTED flag. + */ + export_param(oldpm); + } } paramtab->freenode((HashNode) pm); /* free parameter node */ @@ -2745,7 +2769,7 @@ arrfixenv(char *s, char **t) */ if (t == path) cmdnamtab->emptytable(cmdnamtab); - if ((pm->flags & PM_HASHELEM) || (isset(ALLEXPORT) ? !!pm->old : pm->level)) + if (pm->flags & PM_HASHELEM) return; u = t ? zjoin(t, ':', 1) : ""; len_s = strlen(s); @@ -3013,7 +3037,11 @@ scanendscope(HashNode hn, int flags) pm->flags = (tpm->flags & ~PM_NORESTORE); pm->level = tpm->level; pm->ct = tpm->ct; - pm->env = tpm->env; + if (pm->env) { + delenv(pm->env); + zsfree(pm->env); + } + pm->env = NULL; if (!(tpm->flags & PM_NORESTORE)) switch (PM_TYPE(pm->flags)) { @@ -3035,6 +3063,9 @@ scanendscope(HashNode hn, int flags) break; } zfree(tpm, sizeof(*tpm)); + + if (pm->flags & PM_EXPORTED) + export_param(pm); } else unsetparam_pm(pm, 0, 0); } -- cgit 1.4.1