summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--Completion/compinit1
-rw-r--r--Doc/Zsh/options.yo10
-rw-r--r--Functions/TCP/tcp_expect1
-rw-r--r--Functions/TCP/tcp_open2
-rw-r--r--Functions/TCP/tcp_read4
-rw-r--r--Src/exec.c17
-rw-r--r--Src/options.c1
-rw-r--r--Src/params.c27
-rw-r--r--Src/zsh.h9
10 files changed, 64 insertions, 15 deletions
diff --git a/ChangeLog b/ChangeLog
index 7386c87c2..c6a30dd16 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2005-08-08  Peter Stephenson  <pws@csr.com>
 
+	* 21575 plus unposted changes to Functions/TCP/*:
+	Completion/compinit, Doc/Zsh/options.yo, Functions/TCP/tcp_expect,
+	Functions/TCP/tcp_open, Functions/TCP/tcp_read, Src/exec.c,
+	Src/options.c, Src/params.c, Src/zsh.h: Add WARN_CREATE_GLOBAL
+	option to warn when an assignment in a function creates a globa
+	parameter.
+
 	* 21567: Dan Bullok: Src/utils.c: trash zle when updating window
 	size since otherwise multiline prompts get screwed up.
 
diff --git a/Completion/compinit b/Completion/compinit
index c3b042c04..76792fd0a 100644
--- a/Completion/compinit
+++ b/Completion/compinit
@@ -146,6 +146,7 @@ _comp_options=(
     NO_aliases
     NO_errexit
     NO_octalzeroes
+    NO_warncreateglobal
 )
 
 # And this one should be `eval'ed at the beginning of every entry point
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index e6e6af025..2f0e7d71d 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -460,6 +460,16 @@ item(tt(UNSET) (tt(PLUS()u), ksh: tt(PLUS()u)) <K> <S> <Z>)(
 Treat unset parameters as if they were empty when substituting.
 Otherwise they are treated as an error.
 )
+pindex(WARN_CREATE_GLOBAL)
+cindex(parameters, warning when created globally)
+item(tt(WARN_CREATE_GLOBAL))(
+Print a warning message when a global parameter is created in a function
+by an assignment.  This often indicates that a parameter has not been
+declared local when it should have been.  Parameters explicitly declared
+global from within a function using tt(typeset -g) do not cause a warning.
+Note that there is no warning when a local parameter is assigned to in
+a nested function, which may also indicate an error.
+)
 enditem()
 
 subsect(History)
diff --git a/Functions/TCP/tcp_expect b/Functions/TCP/tcp_expect
index e49f93804..1c63b8def 100644
--- a/Functions/TCP/tcp_expect
+++ b/Functions/TCP/tcp_expect
@@ -84,6 +84,7 @@ while getopts "al:p:qs:t:T:" _expect_opt; do
 done
 (( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
 
+typeset -ga tcp_expect_lines
 tcp_expect_lines=()
 while true; do
   if (( _expect_to_all || _expect_to1 )); then
diff --git a/Functions/TCP/tcp_open b/Functions/TCP/tcp_open
index 1f7a65c9a..cd1afed28 100644
--- a/Functions/TCP/tcp_open
+++ b/Functions/TCP/tcp_open
@@ -200,7 +200,7 @@ done
 
 if [[ -z $TCP_SESS ]]; then
     [[ -z $quiet ]] && print "Setting default TCP session $sessnames[1]"
-    TCP_SESS=$sessnames[1]
+    typeset -g TCP_SESS=$sessnames[1]
 fi
 
 return $stat
diff --git a/Functions/TCP/tcp_read b/Functions/TCP/tcp_read
index cf1b99441..aa30b723d 100644
--- a/Functions/TCP/tcp_read
+++ b/Functions/TCP/tcp_read
@@ -135,7 +135,9 @@ elif (( ! $#read_fds )); then
   read_fds[$tcp_by_name[$TCP_SESS]]=1
 fi
 
+typeset -ga tcp_lines
 tcp_lines=()
+
 local helper_stat=2 skip tpat reply REPLY
 float newtimeout
 
@@ -217,7 +219,7 @@ while (( ${#read_fds} )); do
         $noprint "$line"
     # REPLY is now set to the line with an appropriate prompt.
     tcp_lines+=($REPLY)
-    TCP_LINE=$REPLY TCP_LINE_FD=$read_fd
+    typeset -g TCP_LINE="$REPLY" TCP_LINE_FD="$read_fd"
 
     # Only handle one line from one device at a time unless draining.
     [[ -z $drain ]] && return $stat
diff --git a/Src/exec.c b/Src/exec.c
index 515a41f9b..39308b121 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1649,10 +1649,14 @@ addvars(Estate state, Wordcode pc, int export)
     LinkList vl;
     int xtr, isstr, htok = 0;
     char **arr, **ptr, *name;
+    int flags, augment;
+
     Wordcode opc = state->pc;
     wordcode ac;
     local_list1(svl);
 
+    flags = (locallevel > 0 && isset(WARNCREATEGLOBAL)) ?
+	ASSPM_WARN_CREATE : 0;
     xtr = isset(XTRACE);
     if (xtr) {
 	printprompt4();
@@ -1660,12 +1664,15 @@ addvars(Estate state, Wordcode pc, int export)
     }
     state->pc = pc;
     while (wc_code(ac = *state->pc++) == WC_ASSIGN) {
+	int myflags = flags;
 	name = ecgetstr(state, EC_DUPTOK, &htok);
 	if (htok)
 	    untokenize(name);
+	if (WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC)
+	    myflags |= ASSPM_AUGMENT;
 	if (xtr)
 	    fprintf(xtrerr,
-	    	WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC ? "%s+=" : "%s=", name);
+		WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC ? "%s+=" : "%s=", name);
 	if ((isstr = (WC_ASSIGN_TYPE(ac) == WC_ASSIGN_SCALAR))) {
 	    init_list1(svl, ecgetstr(state, EC_DUPTOK, &htok));
 	    vl = &svl;
@@ -1716,12 +1723,10 @@ addvars(Estate state, Wordcode pc, int export)
 		}
 		allexp = opts[ALLEXPORT];
 		opts[ALLEXPORT] = 1;
-	    	pm = assignsparam(name, val,
-		    WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC);
+	    	pm = assignsparam(name, val, myflags);
 		opts[ALLEXPORT] = allexp;
 	    } else
-	    	pm = assignsparam(name, val,
-		    WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC);
+	    	pm = assignsparam(name, val, myflags);
 	    if (errflag) {
 		state->pc = opc;
 		return;
@@ -1746,7 +1751,7 @@ addvars(Estate state, Wordcode pc, int export)
 	    }
 	    fprintf(xtrerr, ") ");
 	}
-	assignaparam(name, arr, WC_ASSIGN_TYPE2(ac) == WC_ASSIGN_INC);
+	assignaparam(name, arr, myflags);
 	if (errflag) {
 	    state->pc = opc;
 	    return;
diff --git a/Src/options.c b/Src/options.c
index 0cb66b11a..7011b2081 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -211,6 +211,7 @@ static struct optname optns[] = {
 {NULL, "unset",		      OPT_EMULATE|OPT_BSHELL,	 UNSET},
 {NULL, "verbose",	      0,			 VERBOSE},
 {NULL, "vi",		      0,			 VIMODE},
+{NULL, "warncreateglobal",    0,			 WARNCREATEGLOBAL},
 {NULL, "xtrace",	      0,			 XTRACE},
 {NULL, "zle",		      OPT_SPECIAL,		 USEZLE},
 {NULL, "braceexpand",	      OPT_ALIAS, /* ksh/bash */	 -IGNOREBRACES},
diff --git a/Src/params.c b/Src/params.c
index 2bcfb0890..396c97c3a 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -1990,7 +1990,7 @@ gethkparam(char *s)
 
 /**/
 mod_export Param
-assignsparam(char *s, char *val, int augment)
+assignsparam(char *s, char *val, int flags)
 {
     struct value vbuf;
     Value v;
@@ -2011,12 +2011,14 @@ assignsparam(char *s, char *val, int augment)
 	*ss = '\0';
 	if (!(v = getvalue(&vbuf, &s, 1)))
 	    createparam(t, PM_ARRAY);
+	else
+	    flags &= ~ASSPM_WARN_CREATE;
 	*ss = '[';
 	v = NULL;
     } else {
 	if (!(v = getvalue(&vbuf, &s, 1)))
 	    createparam(t, PM_SCALAR);
-	else if ((((v->pm->flags & PM_ARRAY) && !augment) ||
+	else if ((((v->pm->flags & PM_ARRAY) && !(flags & ASSPM_AUGMENT)) ||
 	    	 (v->pm->flags & PM_HASHED)) &&
 		 !(v->pm->flags & (PM_SPECIAL|PM_TIED)) && 
 		 unset(KSHARRAYS)) {
@@ -2024,13 +2026,18 @@ assignsparam(char *s, char *val, int augment)
 	    createparam(t, PM_SCALAR);
 	    v = NULL;
 	}
+	else
+	    flags &= ~ASSPM_WARN_CREATE;
     }
     if (!v && !(v = getvalue(&vbuf, &t, 1))) {
 	unqueue_signals();
 	zsfree(val);
 	return NULL;
     }
-    if (augment) {
+    if ((flags & ASSPM_WARN_CREATE) && v->pm->level == 0)
+	zwarn("scalar parameter %s created globally in function",
+	      v->pm->nam, 0);
+    if (flags & ASSPM_AUGMENT) {
 	if (v->start == 0 && v->end == -1) {
 	    switch (PM_TYPE(v->pm->flags)) {
 	    case PM_SCALAR:
@@ -2109,7 +2116,7 @@ assignsparam(char *s, char *val, int augment)
 
 /**/
 mod_export Param
-assignaparam(char *s, char **val, int augment)
+assignaparam(char *s, char **val, int flags)
 {
     struct value vbuf;
     Value v;
@@ -2127,6 +2134,8 @@ assignaparam(char *s, char **val, int augment)
 	*ss = '\0';
 	if (!(v = getvalue(&vbuf, &s, 1)))
 	    createparam(t, PM_ARRAY);
+	else
+	    flags &= ~ASSPM_WARN_CREATE;
 	*ss = '[';
 	if (v && PM_TYPE(v->pm->flags) == PM_HASHED) {
 	    unqueue_signals();
@@ -2143,7 +2152,7 @@ assignaparam(char *s, char **val, int augment)
 	else if (!(PM_TYPE(v->pm->flags) & (PM_ARRAY|PM_HASHED)) &&
 		 !(v->pm->flags & (PM_SPECIAL|PM_TIED))) {
 	    int uniq = v->pm->flags & PM_UNIQUE;
-	    if (augment) {
+	    if (flags & ASSPM_AUGMENT) {
 	    	/* insert old value at the beginning of the val array */
 		char **new;
 		int lv = arrlen(val);
@@ -2153,12 +2162,13 @@ assignaparam(char *s, char **val, int augment)
 		memcpy(new+1, val, sizeof(char *) * (lv + 1));
 		free(val);
 		val = new;
-		
 	    }
 	    unsetparam(t);
 	    createparam(t, PM_ARRAY | uniq);
 	    v = NULL;
 	}
+	else
+	    flags &= ~ASSPM_WARN_CREATE;
     }
     if (!v)
 	if (!(v = fetchvalue(&vbuf, &t, 1, SCANPM_ASSIGNING))) {
@@ -2167,7 +2177,10 @@ assignaparam(char *s, char **val, int augment)
 	    return NULL;
 	}
 
-    if (augment) {
+    if ((flags & ASSPM_WARN_CREATE) && v->pm->level == 0)
+	zwarn("array parameter %s created globally in function",
+	      v->pm->nam, 0);
+    if (flags & ASSPM_AUGMENT) {
     	if (v->start == 0 && v->end == -1) {
 	    if (PM_TYPE(v->pm->flags) & PM_ARRAY) {
 	    	v->start = arrlen(v->pm->gsu.a->getfn(v->pm));
diff --git a/Src/zsh.h b/Src/zsh.h
index 2c635d02b..b10f0bea2 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -1361,6 +1361,14 @@ struct paramdef {
 #define setsparam(S,V) assignsparam(S,V,0)
 #define setaparam(S,V) assignaparam(S,V,0)
 
+/*
+ * Flags for assignsparam and assignaparam.
+ */
+enum {
+    ASSPM_AUGMENT = 1 << 0,
+    ASSPM_WARN_CREATE = 1 << 1
+};
+
 /* node for named directory hash table (nameddirtab) */
 
 struct nameddir {
@@ -1624,6 +1632,7 @@ enum {
     UNSET,
     VERBOSE,
     VIMODE,
+    WARNCREATEGLOBAL,
     XTRACE,
     USEZLE,
     DVORAK,