From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5573 invoked from network); 14 Jan 1999 18:08:33 -0000 Received: from math.gatech.edu (list@130.207.146.50) by ns1.primenet.com.au with SMTP; 14 Jan 1999 18:08:33 -0000 Received: (from list@localhost) by math.gatech.edu (8.9.1/8.9.1) id MAA06847; Thu, 14 Jan 1999 12:54:53 -0500 (EST) Resent-Date: Thu, 14 Jan 1999 12:54:53 -0500 (EST) Message-ID: From: Amol Deshpande To: zsh-workers@math.gatech.edu, "'Peter Stephenson'" Subject: RE: PATCH: 3.1.5-pws-4: typeset fix Date: Thu, 14 Jan 1999 09:53:53 -0800 X-Mailer: Internet Mail Service (5.5.2524.0) Resent-Message-ID: <"LGD1u2.0.wg1.izYds"@math> Resent-From: zsh-workers@math.gatech.edu X-Mailing-List: archive/latest/4905 X-Loop: zsh-workers@math.gatech.edu Precedence: list Resent-Sender: zsh-workers-request@math.gatech.edu is there a simple fix that will work for 3.0.5 ? thanks, -amol > ---------- > From: Peter Stephenson[SMTP:pws@ibmth.df.unipi.it] > Sent: Thursday, January 14, 1999 7:25 AM > To: zsh-workers@math.gatech.edu > 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 Tel: +39 050 844536 > WWW: http://www.ifh.de/~pws/ > Dipartimento di Fisica, Via Buonarroti 2, 56127 Pisa, Italy >