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

RE: PATCH: 3.1.5-pws-4: typeset fix



is there a simple fix that will work for 3.0.5 ?
thanks,
-amol

> ----------
> From: 	Peter Stephenson[SMTP:pws@xxxxxxxxxxxxxxxxx]
> Sent: 	Thursday, January 14, 1999 7:25 AM
> To: 	zsh-workers@xxxxxxxxxxxxxxx
> Subject: 	PATCH: 3.1.5-pws-4: typeset fix
> 
> "Bart Schaefer" wrote:
> > Haven't looked into it any farther yet, but run zsh -f and then (where
> the
> > name "variable" can be any parameter that is not already set):
> > 
> > zsh% typeset -i variable
> > zsh% typeset -m +i variable
> > zsh% echo $variable
> > 
> > and kablooey.
> 
> Right, that's it.  I know how attached everyone is to the old typeset
> code, but I've finally decided to rewrite it so that it's *gasp*
> almost readable.  So far, I haven't done much else to it, though there
> are probably other rationalisations which could now be added.
> 
> Known changes include:
> 
> - typeset -m behaviour is now identical to the behaviour without the
> m, with the exception that restricted variables are silently ignored
> if necessary (this is what happened before).  There was an additional
> bug hidden here, in that the sequences of commands above, changing
> `variable' from integer to non-integer, could alter the parameter
> table, so it now makes a list of parameters while scanning the table,
> and runs through it later.
> 
> - I removed the restriction on creating array variables (with -a).
> You get an error message if you try to set the array as well.  I
> can't see any problem apart from that.
> 
> - I also de-dangled some else's.
> 
> *** Doc/Zsh/builtins.yo.typeset	Thu Dec 17 17:10:13 1998
> --- Doc/Zsh/builtins.yo	Thu Jan 14 16:19:39 1999
> ***************
> *** 947,955 ****
>   first assignment.
>   )
>   item(tt(-a))(
> ! The names refer to array parameters.  For historical reasons, scalar
> ! parameters are created even when this flag is specified, but the
> ! output is restricted to arrays (including associative arrays).
>   )
>   item(tt(-f))(
>   The names refer to functions rather than parameters.  No assignments
> --- 947,956 ----
>   first assignment.
>   )
>   item(tt(-a))(
> ! The names refer to array parameters.  An array parameter may be
> ! created this way, but it may not be assigned to in the tt(typeset)
> ! statement.  When displaying, both normal and associative arrays are
> ! shown.
>   )
>   item(tt(-f))(
>   The names refer to functions rather than parameters.  No assignments
> *** Src/builtin.c.typeset	Thu Dec 17 12:17:04 1998
> --- Src/builtin.c	Thu Jan 14 15:55:34 1999
> ***************
> *** 1224,1236 ****
>   		if (!editor)
>   		    editor = DEFAULT_FCEDIT;
>   
> ! 		if (fcedit(editor, fil))
>   		    if (stuff(fil))
>   			zwarnnam("fc", "%e: %s", s, errno);
>   		    else {
>   			loop(0,1);
>   			retval = lastval;
>   		    }
>   	    }
>   	}
>   	unlink(fil);
> --- 1224,1237 ----
>   		if (!editor)
>   		    editor = DEFAULT_FCEDIT;
>   
> ! 		if (fcedit(editor, fil)) {
>   		    if (stuff(fil))
>   			zwarnnam("fc", "%e: %s", s, errno);
>   		    else {
>   			loop(0,1);
>   			retval = lastval;
>   		    }
> + 		}
>   	    }
>   	}
>   	unlink(fil);
> ***************
> *** 1464,1469 ****
> --- 1465,1581 ----
>       return &asg;
>   }
>   
> + /* function to set a single parameter */
> + 
> + /**/
> + int
> + typeset_single(char *cname, char *pname, Param pm, int func,
> + 	       int on, int off, int roff, char *value)
> + {
> +     int usepm, tc;
> + 
> +     /* use the existing pm? */
> +     usepm = pm && !(pm->flags & PM_UNSET);
> + 
> +     /* Always use an existing pm if special at current locallevel */
> +     if (pm && (pm->flags & PM_SPECIAL) && pm->level == locallevel)
> + 	usepm = 1;
> + 
> +     /*
> +      * Don't use a non-special existing param if
> +      *   - the local level has changed, and
> +      *   - the function is not `export'.
> +      */
> +     if (usepm && !(pm->flags & PM_SPECIAL) &&
> + 	locallevel != pm->level && func != BIN_EXPORT)
> + 	usepm = 0;
> + 
> +     /* attempting a type conversion? */
> +     if ((tc = usepm && (((off & pm->flags) | (on & ~pm->flags)) &
> + 			(PM_INTEGER|PM_HASHED|PM_ARRAY))))
> + 	usepm = 0;
> +     if (tc && (pm->flags & PM_SPECIAL)) {
> + 	zerrnam(cname, "%s: can't change type of a special parameter",
> + 		pname, 0);
> + 	return 1;
> +     }
> + 
> +     if (usepm) {
> + 	if (!on && !roff && !value) {
> + 	    paramtab->printnode((HashNode)pm, 0);
> + 	    return 0;
> + 	}
> + 	if ((pm->flags & PM_RESTRICTED && isset(RESTRICTED))) {
> + 	    zerrnam(cname, "%s: restricted", pname, 0);
> + 	    return 1;
> + 	}
> + 	if (PM_TYPE(pm->flags) == PM_ARRAY && (on & PM_UNIQUE) &&
> + 	    !(pm->flags & PM_READONLY & ~off))
> + 	    uniqarray((*pm->gets.afn) (pm));
> + 	pm->flags = (pm->flags | on) & ~off;
> + 	/* This auxlen/pm->ct stuff is a nasty hack. */
> + 	if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z | PM_INTEGER)) &&
> + 	    auxlen)
> + 	    pm->ct = auxlen;
> + 	if (!(pm->flags & (PM_ARRAY|PM_HASHED))) {
> + 	    if (pm->flags & PM_EXPORTED) {
> + 		if (!(pm->flags & PM_UNSET) && !pm->env && !value)
> + 		    pm->env = addenv(pname, getsparam(pname));
> + 	    } else if (pm->env) {
> + 		delenv(pm->env);
> + 		zsfree(pm->env);
> + 		pm->env = NULL;
> + 	    }
> + 	    if (value)
> + 		setsparam(pname, ztrdup(value));
> + 	} else if (value) {
> + 	    zwarnnam(cname, "can't assign new value for array %s", pname,
> 0);
> + 	    return 1;
> + 	}
> + 	return 0;
> +     }
> + 
> +     /*
> +      * We're here either because we're creating a new parameter,
> +      * or we're adding a parameter at a different local level,
> +      * or we're converting the type of a parameter.  In the
> +      * last case only, we need to delete the old parameter.
> +      */
> +     if (tc) {
> + 	if (pm->flags & PM_READONLY) {
> + 	    on |= ~off & PM_READONLY;
> + 	    pm->flags &= ~PM_READONLY;
> + 	}
> + 	/*
> + 	 * Try to carry over a value, but not when changing from,
> + 	 * to, or between non-scalar types.
> + 	 */
> + 	if (!value && !((pm->flags|on) & (PM_ARRAY|PM_HASHED)))
> + 	    value = dupstring(getsparam(pname));
> + 	/* pname may point to pm->nam which is about to disappear */
> + 	pname = dupstring(pname);
> + 	unsetparam_pm(pm, 0, 1);
> +     }
> +     /*
> +      * Create a new node for a parameter with the flags in `on' minus
> the
> +      * readonly flag
> +      */
> +     pm = createparam(ztrdup(pname), on & ~PM_READONLY);
> +     DPUTS(!pm, "BUG: parameter not created");
> +     pm->ct = auxlen;
> +     if (func != BIN_EXPORT)
> + 	pm->level = locallevel;
> +     if (value && !(pm->flags & (PM_ARRAY|PM_HASHED)))
> + 	setsparam(pname, ztrdup(value));
> +     pm->flags |= (on & PM_READONLY);
> +     if (value && (pm->flags & (PM_ARRAY|PM_HASHED))) {
> + 	zerrnam(cname, "%s: can't assign initial value for array", pname,
> 0);
> + 	return 1;
> +     }
> + 
> +     return 0;
> + }
> + 
>   /* declare, export, integer, local, readonly, typeset */
>   
>   /**/
> ***************
> *** 1475,1481 ****
>       Comp com;
>       char *optstr = "aiALRZlurtxU";
>       int on = 0, off = 0, roff, bit = PM_ARRAY;
> !     int initon, initoff, of, i;
>       int returnval = 0, printflags = 0;
>   
>       /* hash -f is really the builtin `functions' */
> --- 1587,1593 ----
>       Comp com;
>       char *optstr = "aiALRZlurtxU";
>       int on = 0, off = 0, roff, bit = PM_ARRAY;
> !     int i;
>       int returnval = 0, printflags = 0;
>   
>       /* hash -f is really the builtin `functions' */
> ***************
> *** 1521,1527 ****
> --- 1633,1643 ----
>   
>       /* With the -m option, treat arguments as glob patterns */
>       if (ops['m']) {
> + 	MUSTUSEHEAP("typeset -m");
>   	while ((asg = getasg(*argv++))) {
> + 	    LinkList pmlist = newlinklist();
> + 	    LinkNode pmnode;
> + 
>   	    tokenize(asg->name);   /* expand argument */
>   	    if (!(com = parsereg(asg->name))) {
>   		untokenize(asg->name);
> ***************
> *** 1529,1671 ****
>   		returnval = 1;
>   		continue;
>   	    }
> ! 	    /* If no options or values are given, display all *
> ! 	     * parameters matching the glob pattern.          */
> ! 	    if (!(on || roff || asg->value)) {
> ! 		scanmatchtable(paramtab, com, 0, 0, paramtab->printnode, 0);
> ! 		continue;
> ! 	    }
> ! 	    /* Since either options or values are given, we search   *
> ! 	     * through the parameter table and change all parameters *
> ! 	     * matching the glob pattern to have these flags and/or  *
> ! 	     * value.                                                */
>   	    for (i = 0; i < paramtab->hsize; i++) {
> ! 		for (pm = (Param) paramtab->nodes[i]; pm; pm = (Param)
> pm->next) {
>   		    if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED))
>   			continue;
> ! 		    if (domatch(pm->nam, com, 0)) {
> ! 			/* set up flags if we have any */
> ! 			if (on || roff) {
> ! 			    if (PM_TYPE(pm->flags) == PM_ARRAY && (on &
> PM_UNIQUE) &&
> ! 				!(pm->flags & PM_READONLY & ~off))
> ! 				uniqarray((*pm->gets.afn) (pm));
> ! 			    if ((on & ~pm->flags) & PM_HASHED) {
> ! 				char *nam = ztrdup(pm->nam);
> ! 				unsetparam(nam);
> ! 				pm = createparam(nam, on & ~PM_READONLY);
> ! 				DPUTS(!pm, "BUG: parameter not created");
> ! 			    }
> ! 			    pm->flags = (pm->flags | on) & ~off;
> ! 			    if (PM_TYPE(pm->flags) != PM_ARRAY &&
> ! 				PM_TYPE(pm->flags) != PM_HASHED) {
> ! 				if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z
> | PM_INTEGER)) && auxlen)
> ! 				    pm->ct = auxlen;
> ! 				/* did we just export this? */
> ! 				if ((pm->flags & PM_EXPORTED) && !pm->env) {
> ! 				    pm->env = addenv(pm->nam, (asg->value) ?
> asg->value : getsparam(pm->nam));
> ! 				} else if (!(pm->flags & PM_EXPORTED) &&
> pm->env) {
> ! 				/* did we just unexport this? */
> ! 				    delenv(pm->env);
> ! 				    zsfree(pm->env);
> ! 				    pm->env = NULL;
> ! 				}
> ! 			    }
> ! 			}
> ! 			/* set up a new value if given */
> ! 			if (asg->value) {
> ! 			    setsparam(pm->nam, ztrdup(asg->value));
> ! 			}
> ! 		    }
>   		}
>   	    }
>   	}
>   	return returnval;
>       }
>   
> -     /* Save the values of on, off, and func */
> -     initon = on;
> -     initoff = off;
> -     of = func;
> - 
>       /* Take arguments literally.  Don't glob */
>       while ((asg = getasg(*argv++))) {
> - 	/* restore the original values of on, off, and func */
> - 	on = initon;
> - 	off = initoff;
> - 	func = of;
> - 	on &= ~PM_ARRAY;
> - 
>   	/* check if argument is a valid identifier */
>   	if (!isident(asg->name)) {
>   	    zerr("not an identifier: %s", asg->name, 0);
>   	    returnval = 1;
>   	    continue;
>   	}
> ! 	bit = 0;    /* flag for switching int<->not-int */
> ! 	if ((pm = (Param)paramtab->getnode(paramtab, asg->name)) &&
> ! 	    (((pm->flags & PM_SPECIAL) && pm->level == locallevel) ||
> ! 	     (!(pm->flags & PM_UNSET) &&
> ! 	      ((locallevel == pm->level) || func == BIN_EXPORT) &&
> ! 	      !(bit = (((off & pm->flags) | (on & ~pm->flags)) &
> ! 		       (PM_INTEGER|PM_HASHED)))))) {
> ! 	    /* if no flags or values are given, just print this parameter */
> ! 	    if (!on && !roff && !asg->value) {
> ! 		paramtab->printnode((HashNode) pm, 0);
> ! 		continue;
> ! 	    }
> ! 	    if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED)) {
> ! 		zerrnam(name, "%s: restricted", pm->nam, 0);
> ! 		returnval = 1;
> ! 		continue;
> ! 	    }
> ! 	    if((pm->flags & PM_SPECIAL) &&
> ! 	       PM_TYPE((pm->flags | on) & ~off) != PM_TYPE(pm->flags)) {
> ! 		zerrnam(name, "%s: cannot change type of a special
> parameter",
> ! 		    pm->nam, 0);
> ! 		returnval = 1;
> ! 		continue;
> ! 	    }
> ! 	    if (PM_TYPE(pm->flags) == PM_ARRAY && (on & PM_UNIQUE) &&
> ! 		!(pm->flags & PM_READONLY & ~off))
> ! 		uniqarray((*pm->gets.afn) (pm));
> ! 	    pm->flags = (pm->flags | on) & ~off;
> ! 	    if ((on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z | PM_INTEGER)) &&
> ! 		auxlen)
> ! 		pm->ct = auxlen;
> ! 	    if (PM_TYPE(pm->flags) != PM_ARRAY &&
> ! 		PM_TYPE(pm->flags) != PM_HASHED) {
> ! 		if (pm->flags & PM_EXPORTED) {
> ! 		    if (!(pm->flags & PM_UNSET) && !pm->env && !asg->value)
> ! 			pm->env = addenv(asg->name, getsparam(asg->name));
> ! 		} else if (pm->env) {
> ! 		    delenv(pm->env);
> ! 		    zsfree(pm->env);
> ! 		    pm->env = NULL;
> ! 		}
> ! 		if (asg->value)
> ! 		    setsparam(asg->name, ztrdup(asg->value));
> ! 	    }
> ! 	} else {
> ! 	    if (bit) {
> ! 		if (pm->flags & PM_READONLY) {
> ! 		    on |= ~off & PM_READONLY;
> ! 		    pm->flags &= ~PM_READONLY;
> ! 		}
> ! 		if (!asg->value)
> ! 		    asg->value = dupstring(getsparam(asg->name));
> ! 		unsetparam(asg->name);
> ! 	    }
> ! 	    /* create a new node for a parameter with the *
> ! 	     * flags in `on' minus the readonly flag      */
> ! 	    pm = createparam(ztrdup(asg->name), on & ~PM_READONLY);
> ! 	    DPUTS(!pm, "BUG: parameter not created");
> ! 	    pm->ct = auxlen;
> ! 	    if (func != BIN_EXPORT)
> ! 		pm->level = locallevel;
> ! 	    if (asg->value)
> ! 		setsparam(asg->name, ztrdup(asg->value));
> ! 	    pm->flags |= (on & PM_READONLY);
> ! 	}
>       }
>       return returnval;
>   }
> --- 1645,1689 ----
>   		returnval = 1;
>   		continue;
>   	    }
> ! 	    /*
> ! 	     * Search through the parameter table and change all parameters
> ! 	     * matching the glob pattern to have these flags and/or value.
> ! 	     * Bad news:  if the parameter gets altered, e.g. by
> ! 	     * a type conversion, then paramtab can be shifted around,
> ! 	     * so we need to store the parameters to alter on a separate
> ! 	     * list for later use.	     
> ! 	     */
>   	    for (i = 0; i < paramtab->hsize; i++) {
> ! 		for (pm = (Param) paramtab->nodes[i]; pm;
> ! 		     pm = (Param) pm->next) {
>   		    if ((pm->flags & PM_RESTRICTED) && isset(RESTRICTED))
>   			continue;
> ! 		    if (domatch(pm->nam, com, 0))
> ! 			addlinknode(pmlist, pm);
>   		}
>   	    }
> + 	    for (pmnode = firstnode(pmlist); pmnode; incnode(pmnode)) {
> + 		pm = (Param) getdata(pmnode);
> + 		if (typeset_single(name, pm->nam, pm, func, on, off, roff,
> + 				   asg->value))
> + 		    returnval = 1;
> + 	    }
>   	}
>   	return returnval;
>       }
>   
>       /* Take arguments literally.  Don't glob */
>       while ((asg = getasg(*argv++))) {
>   	/* check if argument is a valid identifier */
>   	if (!isident(asg->name)) {
>   	    zerr("not an identifier: %s", asg->name, 0);
>   	    returnval = 1;
>   	    continue;
>   	}
> ! 	if (typeset_single(name, asg->name,
> ! 			   (Param)paramtab->getnode(paramtab, asg->name),
> ! 			   func, on, off, roff, asg->value))
> ! 	    returnval = 1;
>       }
>       return returnval;
>   }
> ***************
> *** 2778,2785 ****
>   		LASTALLOC_RETURN;
>   	    }
>   	}
> ! 	if (in_exit++ && from_signal)
>   	    LASTALLOC_RETURN;
>   	if (isset(MONITOR))
>   	    /* send SIGHUP to any jobs left running  */
>   	    killrunjobs(from_signal);
> --- 2796,2804 ----
>   		LASTALLOC_RETURN;
>   	    }
>   	}
> ! 	if (in_exit++ && from_signal) {
>   	    LASTALLOC_RETURN;
> + 	}
>   	if (isset(MONITOR))
>   	    /* send SIGHUP to any jobs left running  */
>   	    killrunjobs(from_signal);
> ***************
> *** 3181,3193 ****
>   	    }
>   	    if (c == EOF || (c == '\n' && !zbuf))
>   		break;
> ! 	    if (!bslash && isep(c) && bptr == buf)
>   		if (iwsep(c))
>   		    continue;
>   		else if (!first) {
>   		    first = 1;
>   		    continue;
>   		}
>   	    bslash = c == '\\' && !bslash && !ops['r'];
>   	    if (bslash)
>   		continue;
> --- 3200,3213 ----
>   	    }
>   	    if (c == EOF || (c == '\n' && !zbuf))
>   		break;
> ! 	    if (!bslash && isep(c) && bptr == buf) {
>   		if (iwsep(c))
>   		    continue;
>   		else if (!first) {
>   		    first = 1;
>   		    continue;
>   		}
> + 	    }
>   	    bslash = c == '\\' && !bslash && !ops['r'];
>   	    if (bslash)
>   		continue;
> ***************
> *** 3240,3246 ****
>       char cc, retry = 0;
>   
>       /* use zbuf if possible */
> !     if (zbuf)
>   	/* If zbuf points to anything, it points to the next character in
> the
>   	buffer.  This may be a null byte to indicate EOF.  If reading from
> the
>   	buffer, move on the buffer pointer. */
> --- 3260,3266 ----
>       char cc, retry = 0;
>   
>       /* use zbuf if possible */
> !     if (zbuf) {
>   	/* If zbuf points to anything, it points to the next character in
> the
>   	buffer.  This may be a null byte to indicate EOF.  If reading from
> the
>   	buffer, move on the buffer pointer. */
> ***************
> *** 3248,3253 ****
> --- 3268,3274 ----
>   	    return zbuf++, STOUC(*zbuf++ ^ 32);
>   	else
>   	    return (*zbuf) ? STOUC(*zbuf++) : EOF;
> +     }
>       for (;;) {
>   	/* read a character from readfd */
>   	switch (read(readfd, &cc, 1)) {
> 
> -- 
> Peter Stephenson <pws@xxxxxxxxxxxxxxxxx>       Tel: +39 050 844536
> WWW:  http://www.ifh.de/~pws/
> Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy
> 



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