about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Doc/Zsh/builtins.yo15
-rw-r--r--Doc/Zsh/params.yo18
-rw-r--r--Src/builtin.c26
-rw-r--r--Src/params.c71
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  <pws@cambridgesiliconradio.com>
+
+	* 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 <wischnow@informatik.hu-berlin.de>
 
 	* 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);
@@ -1446,11 +1454,30 @@ getnumvalue(Value v)
 }
 
 /**/
+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);
     }