zsh-workers
 help / color / mirror / code / Atom feed
From: Peter Stephenson <pws@ibmth.df.unipi.it>
To: zsh-workers@math.gatech.edu
Subject: PATCH: 3.1.5-pws-4: typeset fix
Date: Thu, 14 Jan 1999 16:25:58 +0100	[thread overview]
Message-ID: <9901141526.AA73314@ibmth.df.unipi.it> (raw)
In-Reply-To: ""Bart Schaefer""'s message of "Wed, 13 Jan 1999 08:08:08 NFT." <990113080808.ZM17359@candle.brasslantern.com>

"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@ibmth.df.unipi.it>       Tel: +39 050 844536
WWW:  http://www.ifh.de/~pws/
Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy


  reply	other threads:[~1999-01-14 15:49 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-01-13 16:08 Repeatable zsh crash in 3.0.5 and 3.1.5-pws-4 Bart Schaefer
1999-01-14 15:25 ` Peter Stephenson [this message]
1999-01-14 16:06   ` PATCH: 3.1.5-pws-4: typeset fix Andrej Borsenkow
1999-01-14 15:55     ` Peter Stephenson
1999-01-15  6:53       ` zsh 3.1.5 core dumps on Solaris 7 Jozsef Kadlecsik
1999-01-15  8:28         ` Peter Stephenson
1999-01-15  8:39         ` Jozsef Kadlecsik
1999-01-15  8:43           ` PATCH: 3.1.5.x: " Peter Stephenson
1999-01-15  8:54           ` Jozsef Kadlecsik
1999-01-15  8:52             ` PATCH: (2): " Peter Stephenson
1999-01-14 17:53 PATCH: 3.1.5-pws-4: typeset fix Amol Deshpande

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9901141526.AA73314@ibmth.df.unipi.it \
    --to=pws@ibmth.df.unipi.it \
    --cc=zsh-workers@math.gatech.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/zsh/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).