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

PATCH: useheap (was: Re: PATCH: Improved _mailboxes)



Peter Stephenson wrote:

> I'm delighted about the vanishing of useheap --- this was sort of vaguely
> on my to-do list, at least to think about over a cup of tea.

I needed several cups of Darjeeling...

>  This should
> reduce the number of memory leaks dramatically.  (Not that we have memory
> leaks, of course.)

(What's that?)


Not surprisingly, this patch is even larger, although there really
isn't that much to say about it.

Some functions (those that are used in few places) have got a new
argument (always the last one),named `heap' saying if the memory
should been taken from heap memory (if != 0). Other functions have got 
a sister. One uses heap memory and the other one uses zalloc()ed
memory. As usual, the latter one starts with a `z', as in `zarrdup()'
(versus `arrdup()'). This difference may sound weird, but actually,
this convention was already used.

Functions (and, btw, macros) with a `z' are mostly the already
mentioned zarrdup() and the list functions like znewlinklist() and
zaddlinknode().

Oh, and dupstring() now really only allocates heap memory.


Ok, most of the work was to find out where functions like dupstring()
and arrdup() were used to allocate non-heap memory and removing and
re-indenting all those {PERM,HEAP}ALLOCs.


As I said, I've already tested this quite a bit, but with memory one
can almost never be sure. So, if you really want to help us, it might
be a good idea to enable all the zsh-mem bells and whistles, including 
mem-debug and secure-free. Should make bugs easier to track down. Or
maybe someone has a good memory allocation verifier? Every help in
testing, as usual, very much appreciated.


Bye
 Sven

diff -ru ../z.old/Src/Builtins/sched.c Src/Builtins/sched.c
--- ../z.old/Src/Builtins/sched.c	Wed Feb 23 14:22:13 2000
+++ Src/Builtins/sched.c	Wed Feb 23 14:23:51 2000
@@ -143,9 +143,7 @@
     of scheduled commands. */
     sch = (struct schedcmd *) zcalloc(sizeof *sch);
     sch->time = t;
-    PERMALLOC {
-	sch->cmd = zjoin(argv, ' ');
-    } LASTALLOC;
+    sch->cmd = zjoin(argv, ' ', 0);
     sch->next = NULL;
     for (sch2 = (struct schedcmd *)&schedcmds; sch2->next; sch2 = sch2->next);
     sch2->next = sch;
diff -ru ../z.old/Src/Modules/example.c Src/Modules/example.c
--- ../z.old/Src/Modules/example.c	Wed Feb 23 14:22:11 2000
+++ Src/Modules/example.c	Wed Feb 23 14:23:51 2000
@@ -70,9 +70,7 @@
     zsfree(strparam);
     strparam = ztrdup(*oargs ? *oargs : "");
     freearray(arrparam);
-    PERMALLOC {
-	arrparam = arrdup(oargs);
-    } LASTALLOC;
+    arrparam = zarrdup(oargs);
     return 0;
 }
 
diff -ru ../z.old/Src/Modules/mapfile.c Src/Modules/mapfile.c
--- ../z.old/Src/Modules/mapfile.c	Wed Feb 23 14:22:12 2000
+++ Src/Modules/mapfile.c	Wed Feb 23 14:23:51 2000
@@ -248,7 +248,7 @@
     val = NULL;
     if ((fd = open(fname, O_RDONLY | O_NOCTTY)) >= 0) {
 	LinkList ll;
-	MUSTUSEHEAP("mapfile:get_contents");
+
 	if ((ll = readoutput(fd, 1)))
 	    val = peekfirst(ll);
     }
@@ -264,30 +264,27 @@
     char *contents;
     Param pm = NULL;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR;
-	pm->sets.cfn = setpmmapfile;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = unsetpmmapfile;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-
-	pm->flags |= (mapfile_pm->flags & PM_READONLY);
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR;
+    pm->sets.cfn = setpmmapfile;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = unsetpmmapfile;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
 
-	/* Set u.str to contents of file given by name */
-	if ((contents = get_contents(pm->nam)))
-	    pm->u.str = contents;
-	else {
-	    pm->u.str = "";
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
+    pm->flags |= (mapfile_pm->flags & PM_READONLY);
 
+    /* Set u.str to contents of file given by name */
+    if ((contents = get_contents(pm->nam)))
+	pm->u.str = contents;
+    else {
+	pm->u.str = "";
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
diff -ru ../z.old/Src/Modules/parameter.c Src/Modules/parameter.c
--- ../z.old/Src/Modules/parameter.c	Wed Feb 23 14:22:12 2000
+++ Src/Modules/parameter.c	Wed Feb 23 14:23:51 2000
@@ -136,27 +136,24 @@
 {
     Param rpm, pm = NULL;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR | PM_READONLY;
-	pm->sets.cfn = NULL;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = NULL;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-	if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) &&
-	    !(rpm->flags & PM_UNSET))
-	    pm->u.str = paramtypestr(rpm);
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR | PM_READONLY;
+    pm->sets.cfn = NULL;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = NULL;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+    if ((rpm = (Param) realparamtab->getnode(realparamtab, name)) &&
+	!(rpm->flags & PM_UNSET))
+	pm->u.str = paramtypestr(rpm);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -257,34 +254,30 @@
 	cmdnamtab->filltable(cmdnamtab);
 	cmd = (Cmdnam) cmdnamtab->getnode(cmdnamtab, name);
     }
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR;
-	pm->sets.cfn = setpmcommand;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = unsetpmcommand;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-	if (cmd) {
-	    if (cmd->flags & HASHED)
-		pm->u.str = cmd->u.cmd;
-	    else {
-		pm->u.str = zhalloc(strlen(*(cmd->u.name)) +
-				    strlen(name) + 2);
-		strcpy(pm->u.str, *(cmd->u.name));
-		strcat(pm->u.str, "/");
-		strcat(pm->u.str, name);
-	    }
-	} else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR;
+    pm->sets.cfn = setpmcommand;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = unsetpmcommand;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+    if (cmd) {
+	if (cmd->flags & HASHED)
+	    pm->u.str = cmd->u.cmd;
+	else {
+	    pm->u.str = zhalloc(strlen(*(cmd->u.name)) + strlen(name) + 2);
+	    strcpy(pm->u.str, *(cmd->u.name));
+	    strcat(pm->u.str, "/");
+	    strcat(pm->u.str, name);
+	}
+    } else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -344,32 +337,28 @@
 
     val = metafy(val, strlen(val), META_REALLOC);
 
-    HEAPALLOC {
-	prog = parse_string(val, 1);
-    } LASTALLOC;
+    prog = parse_string(val, 1);
 
     if (!prog || prog == &dummy_eprog) {
 	zwarn("invalid function definition", value, 0);
 	zsfree(val);
 	return;
     }
-    PERMALLOC {
-	shf = (Shfunc) zalloc(sizeof(*shf));
-	shf->funcdef = dupeprog(prog);
-	shf->flags = dis;
-
-	if (!strncmp(name, "TRAP", 4) &&
-	    (sn = getsignum(name + 4)) != -1) {
-	    if (settrap(sn, shf->funcdef)) {
-		freeeprog(shf->funcdef);
-		zfree(shf, sizeof(*shf));
-		zsfree(val);
-		LASTALLOC_RETURN;
-	    }
-	    sigtrapped[sn] |= ZSIG_FUNC;
+    shf = (Shfunc) zalloc(sizeof(*shf));
+    shf->funcdef = zdupeprog(prog);
+    shf->flags = dis;
+
+    if (!strncmp(name, "TRAP", 4) &&
+	(sn = getsignum(name + 4)) != -1) {
+	if (settrap(sn, shf->funcdef)) {
+	    freeeprog(shf->funcdef);
+	    zfree(shf, sizeof(*shf));
+	    zsfree(val);
+	    return;
 	}
-	shfunctab->addnode(shfunctab, ztrdup(name), shf);
-    } LASTALLOC;
+	sigtrapped[sn] |= ZSIG_FUNC;
+    }
+    shfunctab->addnode(shfunctab, ztrdup(name), shf);
     zsfree(val);
 }
 
@@ -442,41 +431,38 @@
     Shfunc shf;
     Param pm = NULL;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR;
-	pm->sets.cfn = (dis ? setpmdisfunction : setpmfunction);
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = unsetpmfunction;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-
-	if ((shf = (Shfunc) shfunctab->getnode2(shfunctab, name)) &&
-	    (dis ? (shf->flags & DISABLED) : !(shf->flags & DISABLED))) {
-	    if (shf->flags & PM_UNDEFINED) {
-		pm->u.str = dyncat("builtin autoload -X",
-				   ((shf->flags & PM_UNALIASED) ?
-				    ((shf->flags & PM_TAGGED) ? "Ut" : "U") :
-				    ((shf->flags & PM_TAGGED) ? "t" : "")));
-	    } else {
-		char *t = getpermtext(shf->funcdef, NULL), *h;
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR;
+    pm->sets.cfn = (dis ? setpmdisfunction : setpmfunction);
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = unsetpmfunction;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+
+    if ((shf = (Shfunc) shfunctab->getnode2(shfunctab, name)) &&
+	(dis ? (shf->flags & DISABLED) : !(shf->flags & DISABLED))) {
+	if (shf->flags & PM_UNDEFINED) {
+	    pm->u.str = dyncat("builtin autoload -X",
+			       ((shf->flags & PM_UNALIASED) ?
+				((shf->flags & PM_TAGGED) ? "Ut" : "U") :
+				((shf->flags & PM_TAGGED) ? "t" : "")));
+	} else {
+	    char *t = getpermtext(shf->funcdef, NULL), *h;
 
-		h = dupstring(t);
-		zsfree(t);
-		unmetafy(h, NULL);
+	    h = dupstring(t);
+	    zsfree(t);
+	    unmetafy(h, NULL);
 
-		pm->u.str = h;
-	    }
-	} else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
+	    pm->u.str = h;
 	}
-    } LASTALLOC;
-
+    } else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -583,30 +569,27 @@
     Param pm = NULL;
     Builtin bn;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR | PM_READONLY;
-	pm->sets.cfn = NULL;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = NULL;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-	if ((bn = (Builtin) builtintab->getnode2(builtintab, name)) &&
-	    (dis ? (bn->flags & DISABLED) : !(bn->flags & DISABLED))) {
-	    char *t = ((bn->handlerfunc || (bn->flags & BINF_PREFIX)) ?
-		       "defined" : "undefined");
-
-	    pm->u.str = dupstring(t);
-	} else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR | PM_READONLY;
+    pm->sets.cfn = NULL;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = NULL;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+    if ((bn = (Builtin) builtintab->getnode2(builtintab, name)) &&
+	(dis ? (bn->flags & DISABLED) : !(bn->flags & DISABLED))) {
+	char *t = ((bn->handlerfunc || (bn->flags & BINF_PREFIX)) ?
+		   "defined" : "undefined");
+
+	pm->u.str = dupstring(t);
+    } else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -775,27 +758,24 @@
     Param pm = NULL;
     int n;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR;
-	pm->sets.cfn = setpmoption;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = unsetpmoption;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-
-	if ((n = optlookup(name)))
-	    pm->u.str = dupstring(opts[n] ? "on" : "off");
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR;
+    pm->sets.cfn = setpmoption;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = unsetpmoption;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
 
+    if ((n = optlookup(name)))
+	pm->u.str = dupstring(opts[n] ? "on" : "off");
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -871,57 +851,54 @@
     char *type = NULL;
     LinkNode node;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR | PM_READONLY;
-	pm->sets.cfn = NULL;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = NULL;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-
-	if (!type) {
-	    Module m;
-
-	    for (node = firstnode(modules); node; incnode(node)) {
-		m = (Module) getdata(node);
-		if (m->u.handle && !(m->flags & MOD_UNLOAD) &&
-		    !strcmp(name, m->nam)) {
-		    type = "loaded";
-		    break;
-		}
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR | PM_READONLY;
+    pm->sets.cfn = NULL;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = NULL;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+
+    if (!type) {
+	Module m;
+
+	for (node = firstnode(modules); node; incnode(node)) {
+	    m = (Module) getdata(node);
+	    if (m->u.handle && !(m->flags & MOD_UNLOAD) &&
+		!strcmp(name, m->nam)) {
+		type = "loaded";
+		break;
 	    }
 	}
-	modpmname = name;
-	modpmfound = 0;
-	if (!type) {
-	    scanhashtable(builtintab, 0, 0, 0, modpmbuiltinscan, 0);
-	    if (!modpmfound) {
-		Conddef p;
-
-		for (p = condtab; p; p = p->next)
-		    if (p->module && !strcmp(name, p->module)) {
-			modpmfound = 1;
-			break;
-		    }
-		if (!modpmfound)
-		    scanhashtable(realparamtab, 0, 0, 0, modpmparamscan, 0);
-	    }
-	    if (modpmfound)
-		type = "autoloaded";
-	}
-	if (type)
-	    pm->u.str = dupstring(type);
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
+    }
+    modpmname = name;
+    modpmfound = 0;
+    if (!type) {
+	scanhashtable(builtintab, 0, 0, 0, modpmbuiltinscan, 0);
+	if (!modpmfound) {
+	    Conddef p;
+
+	    for (p = condtab; p; p = p->next)
+		if (p->module && !strcmp(name, p->module)) {
+		    modpmfound = 1;
+		    break;
+		}
+	    if (!modpmfound)
+		scanhashtable(realparamtab, 0, 0, 0, modpmparamscan, 0);
 	}
-    } LASTALLOC;
-
+	if (modpmfound)
+	    type = "autoloaded";
+    }
+    if (type)
+	pm->u.str = dupstring(type);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -991,12 +968,10 @@
 dirssetfn(Param pm, char **x)
 {
     if (!incleanup) {
-	PERMALLOC {
-	    freelinklist(dirstack, freestr);
-	    dirstack = newlinklist();
-	    while (x && *x)
-		addlinknode(dirstack, ztrdup(*x++));
-	} LASTALLOC;
+	freelinklist(dirstack, freestr);
+	dirstack = znewlinklist();
+	while (x && *x)
+	    zaddlinknode(dirstack, ztrdup(*x++));
     }
     if (x)
 	freearray(x);
@@ -1026,26 +1001,23 @@
     Param pm = NULL;
     Histent he;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR | PM_READONLY;
-	pm->sets.cfn = NULL;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = NULL;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-	if ((he = quietgethist(atoi(name))))
-	    pm->u.str = dupstring(he->text);
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR | PM_READONLY;
+    pm->sets.cfn = NULL;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = NULL;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+    if ((he = quietgethist(atoi(name))))
+	pm->u.str = dupstring(he->text);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -1145,29 +1117,26 @@
     Param pm = NULL;
     int job;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR | PM_READONLY;
-	pm->sets.cfn = NULL;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = NULL;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-
-	if ((job = atoi(name)) >= 1 && job < MAXJOB &&
-	    jobtab[job].stat && jobtab[job].procs &&
-	    !(jobtab[job].stat & STAT_NOPRINT))
-	    pm->u.str = pmjobtext(job);
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR | PM_READONLY;
+    pm->sets.cfn = NULL;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = NULL;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+
+    if ((job = atoi(name)) >= 1 && job < MAXJOB &&
+	jobtab[job].stat && jobtab[job].procs &&
+	!(jobtab[job].stat & STAT_NOPRINT))
+	pm->u.str = pmjobtext(job);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -1251,29 +1220,26 @@
     Param pm = NULL;
     int job;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR | PM_READONLY;
-	pm->sets.cfn = NULL;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = NULL;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-
-	if ((job = atoi(name)) >= 1 && job < MAXJOB &&
-	    jobtab[job].stat && jobtab[job].procs &&
-	    !(jobtab[job].stat & STAT_NOPRINT))
-	    pm->u.str = pmjobstate(job);
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR | PM_READONLY;
+    pm->sets.cfn = NULL;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = NULL;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+
+    if ((job = atoi(name)) >= 1 && job < MAXJOB &&
+	jobtab[job].stat && jobtab[job].procs &&
+	!(jobtab[job].stat & STAT_NOPRINT))
+	pm->u.str = pmjobstate(job);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -1329,29 +1295,26 @@
     Param pm = NULL;
     int job;
 
-    HEAPALLOC {
-       pm = (Param) zhalloc(sizeof(struct param));
-       pm->nam = dupstring(name);
-       pm->flags = PM_SCALAR | PM_READONLY;
-       pm->sets.cfn = NULL;
-       pm->gets.cfn = strgetfn;
-       pm->unsetfn = NULL;
-       pm->ct = 0;
-       pm->env = NULL;
-       pm->ename = NULL;
-       pm->old = NULL;
-       pm->level = 0;
-
-       if ((job = atoi(name)) >= 1 && job < MAXJOB &&
-           jobtab[job].stat && jobtab[job].procs &&
-           !(jobtab[job].stat & STAT_NOPRINT))
-           pm->u.str = pmjobdir(job);
-       else {
-           pm->u.str = dupstring("");
-           pm->flags |= PM_UNSET;
-       }
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR | PM_READONLY;
+    pm->sets.cfn = NULL;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = NULL;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+
+    if ((job = atoi(name)) >= 1 && job < MAXJOB &&
+	jobtab[job].stat && jobtab[job].procs &&
+	!(jobtab[job].stat & STAT_NOPRINT))
+	pm->u.str = pmjobdir(job);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -1462,27 +1425,24 @@
     Param pm = NULL;
     Nameddir nd;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR;
-	pm->sets.cfn = setpmnameddir;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = unsetpmnameddir;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-	if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
-	    !(nd->flags & ND_USERNAME))
-	    pm->u.str = dupstring(nd->dir);
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR;
+    pm->sets.cfn = setpmnameddir;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = unsetpmnameddir;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+    if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
+	!(nd->flags & ND_USERNAME))
+	pm->u.str = dupstring(nd->dir);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -1529,27 +1489,24 @@
 
     nameddirtab->filltable(nameddirtab);
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR | PM_READONLY;
-	pm->sets.cfn = NULL;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = NULL;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-	if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
-	    (nd->flags & ND_USERNAME))
-	    pm->u.str = dupstring(nd->dir);
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR | PM_READONLY;
+    pm->sets.cfn = NULL;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = NULL;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+    if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)) &&
+	(nd->flags & ND_USERNAME))
+	pm->u.str = dupstring(nd->dir);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
@@ -1715,30 +1672,27 @@
     Param pm = NULL;
     Alias al;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR;
-	pm->sets.cfn = (global ? (dis ? setpmdisgalias : setpmgalias) :
-			(dis ? setpmdisralias : setpmralias));
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = unsetpmalias;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-	if ((al = (Alias) aliastab->getnode2(aliastab, name)) &&
-	    ((global && (al->flags & ALIAS_GLOBAL)) ||
-	     (!global && !(al->flags & ALIAS_GLOBAL))) &&
-	    (dis ? (al->flags & DISABLED) : !(al->flags & DISABLED)))
-	    pm->u.str = dupstring(al->text);
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR;
+    pm->sets.cfn = (global ? (dis ? setpmdisgalias : setpmgalias) :
+		    (dis ? setpmdisralias : setpmralias));
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = unsetpmalias;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+    if ((al = (Alias) aliastab->getnode2(aliastab, name)) &&
+	((global && (al->flags & ALIAS_GLOBAL)) ||
+	 (!global && !(al->flags & ALIAS_GLOBAL))) &&
+	(dis ? (al->flags & DISABLED) : !(al->flags & DISABLED)))
+	pm->u.str = dupstring(al->text);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
diff -ru ../z.old/Src/Modules/zftp.c Src/Modules/zftp.c
--- ../z.old/Src/Modules/zftp.c	Wed Feb 23 14:22:12 2000
+++ Src/Modules/zftp.c	Wed Feb 23 14:23:52 2000
@@ -2887,17 +2887,15 @@
     }
 
     if (!nptr) {
-	PERMALLOC {
-	    zfsess = (Zftp_session) zcalloc(sizeof(struct zftp_session));
-	    zfsess->name = ztrdup(nm);
-	    zfsess->cfd = zfsess->dfd = -1;
-	    zfsess->params = (char **) zcalloc(sizeof(zfparams));
-	    addlinknode(zfsessions, zfsess);
-
-	    zfsesscnt++;
-	    zfstatusp = (int *)zrealloc(zfstatusp, sizeof(int)*zfsesscnt);
-	    zfstatusp[zfsessno] = 0;
-	} LASTALLOC;
+	zfsess = (Zftp_session) zcalloc(sizeof(struct zftp_session));
+	zfsess->name = ztrdup(nm);
+	zfsess->cfd = zfsess->dfd = -1;
+	zfsess->params = (char **) zcalloc(sizeof(zfparams));
+	zaddlinknode(zfsessions, zfsess);
+
+	zfsesscnt++;
+	zfstatusp = (int *)zrealloc(zfstatusp, sizeof(int)*zfsesscnt);
+	zfstatusp[zfsessno] = 0;
     }
 
     zfsetparam("ZFTP_SESSION", ztrdup(zfsess->name), ZFPM_READONLY);
@@ -3221,9 +3219,7 @@
 	/* default preferences if user deletes variable */
 	zfprefs = ZFPF_SNDP|ZFPF_PASV;
     
-	PERMALLOC {
-	    zfsessions = newlinklist();
-	} LASTALLOC;
+	zfsessions = znewlinklist();
 	newsession("default");
     }
 
diff -ru ../z.old/Src/Modules/zprof.c Src/Modules/zprof.c
--- ../z.old/Src/Modules/zprof.c	Wed Feb 23 14:22:12 2000
+++ Src/Modules/zprof.c	Wed Feb 23 14:23:52 2000
@@ -224,28 +224,24 @@
     double prev, now;
 
     if (!(f = findpfunc(name))) {
-	PERMALLOC {
-	    f = (Pfunc) zalloc(sizeof(*f));
-	    f->name = ztrdup(name);
-	    f->calls = 0;
-	    f->time = f->self = 0.0;
-	    f->next = calls;
-	    calls = f;
-	    ncalls++;
-	} LASTALLOC;
+	f = (Pfunc) zalloc(sizeof(*f));
+	f->name = ztrdup(name);
+	f->calls = 0;
+	f->time = f->self = 0.0;
+	f->next = calls;
+	calls = f;
+	ncalls++;
     }
     if (stack) {
 	if (!(a = findparc(stack->p, f))) {
-	    PERMALLOC {
-		a = (Parc) zalloc(sizeof(*a));
-		a->from = stack->p;
-		a->to = f;
-		a->calls = 0;
-		a->time = a->self = 0.0;
-		a->next = arcs;
-		arcs = a;
-		narcs++;
-	    } LASTALLOC;
+	    a = (Parc) zalloc(sizeof(*a));
+	    a->from = stack->p;
+	    a->to = f;
+	    a->calls = 0;
+	    a->time = a->self = 0.0;
+	    a->next = arcs;
+	    arcs = a;
+	    narcs++;
 	}
     }
     sf.prev = stack;
diff -ru ../z.old/Src/Modules/zpty.c Src/Modules/zpty.c
--- ../z.old/Src/Modules/zpty.c	Wed Feb 23 14:22:13 2000
+++ Src/Modules/zpty.c	Wed Feb 23 14:23:52 2000
@@ -307,9 +307,7 @@
     p = (Ptycmd) zalloc(sizeof(*p));
 
     p->name = ztrdup(pname);
-    PERMALLOC {
-	p->args = arrdup(args);
-    } LASTALLOC;
+    p->args = zarrdup(args);
     p->fd = master;
     p->pid = pid;
     p->echo = echo;
diff -ru ../z.old/Src/Modules/zutil.c Src/Modules/zutil.c
--- ../z.old/Src/Modules/zutil.c	Wed Feb 23 14:22:13 2000
+++ Src/Modules/zutil.c	Wed Feb 23 14:23:53 2000
@@ -115,9 +115,7 @@
 
 	    if (p->vals)
 		freearray(p->vals);
-	    PERMALLOC {
-		p->vals = arrdup(vals);
-	    } LASTALLOC;
+	    p->vals = zarrdup(vals);
 
 	    return;
 	}
@@ -127,9 +125,7 @@
     p = (Stypat) zalloc(sizeof(*p));
     p->pat = ztrdup(pat);
     p->prog = prog;
-    PERMALLOC {
-	p->vals = arrdup(vals);
-    } LASTALLOC;
+    p->vals = zarrdup(vals);
     p->next = NULL;
 
     /* Calculate the weight. */
@@ -353,9 +349,7 @@
 	    int val;
 
 	    if ((s = lookupstyle(args[1], args[2])) && s->vals[0]) {
-		PERMALLOC {
-		    ret = sepjoin(s->vals, (args[4] ? args[4] : " "));
-		} LASTALLOC;
+		ret = sepjoin(s->vals, (args[4] ? args[4] : " "), 0);
 		val = 0;
 	    } else {
 		ret = ztrdup("");
@@ -397,16 +391,12 @@
 	    int val;
 
 	    if ((s = lookupstyle(args[1], args[2]))) {
-		PERMALLOC {
-		    ret = arrdup(s->vals);
-		} LASTALLOC;
+		ret = zarrdup(s->vals);
 		val = 0;
 	    } else {
 		char *dummy = NULL;
 
-		PERMALLOC {
-		    ret = arrdup(&dummy);
-		} LASTALLOC;
+		ret = zarrdup(&dummy);
 		val = 1;
 	    }
 	    if (args[0][1] == 'a')
@@ -697,14 +687,12 @@
 {
     char **a;
 
-    PERMALLOC {
-	a = getaparam("match");
-	m->match = a ? arrdup(a) : NULL;
-	a = getaparam("mbegin");
-	m->mbegin = a ? arrdup(a) : NULL;
-	a = getaparam("mend");
-	m->mend = a ? arrdup(a) : NULL;
-    } LASTALLOC;
+    a = getaparam("match");
+    m->match = a ? zarrdup(a) : NULL;
+    a = getaparam("mbegin");
+    m->mbegin = a ? zarrdup(a) : NULL;
+    a = getaparam("mend");
+    m->mend = a ? zarrdup(a) : NULL;
 }
 
 static void
@@ -770,7 +758,7 @@
 
 	for (innode = firstnode(in); innode; innode = nextnode(innode)) {
 	    RParseBranch *inbranch = getdata(innode);
-	    RParseBranch *br = ncalloc(sizeof(*br));
+	    RParseBranch *br = hcalloc(sizeof(*br));
 
 	    br->state = inbranch->state;
 	    br->actions = newlinklist();
@@ -804,7 +792,7 @@
 	      (3 <= l && s[l - 2] == '/' && (s[l - 1] == '+' ||
 					     s[l - 1] == '-'))))
 	    return 1;
-	st = ncalloc(sizeof(*st));
+	st = hcalloc(sizeof(*st));
 	st->branches = newlinklist();
 	st->cutoff = s[l - 1];
 	if (s[l - 1] == '/') {
@@ -830,7 +818,7 @@
 	    int l = patternlen + 12; /* (#b)((#B)...)...* */
 	    if(lookahead)
 	        l += lookaheadlen + 4; /* (#B)... */
-	    cp = st->pattern = ncalloc(l);
+	    cp = st->pattern = hcalloc(l);
 	    strcpy(cp, "(#b)((#B)");
 	    cp += 9;
 	    strcpy(cp, pattern);
@@ -849,7 +837,7 @@
 	if ((s = *rparseargs) && *s == '-') {
 	    rparseargs++;
 	    l = strlen(s);
-	    st->guard = ncalloc(l);
+	    st->guard = hcalloc(l);
 	    memcpy(st->guard, s + 1, l - 1);
 	    st->guard[l - 1] = '\0';
 	} else
@@ -857,19 +845,19 @@
 	if ((s = *rparseargs) && *s == ':') {
 	    rparseargs++;
 	    l = strlen(s);
-	    st->action = ncalloc(l);
+	    st->action = hcalloc(l);
 	    memcpy(st->action, s + 1, l - 1);
 	    st->action[l - 1] = '\0';
 	} else
 	    st->action = NULL;
 	result->nullacts = NULL;
 	result->in = newlinklist();
-	br = ncalloc(sizeof(*br));
+	br = hcalloc(sizeof(*br));
 	br->state = st;
 	br->actions = newlinklist();
 	addlinknode(result->in, br);
 	result->out = newlinklist();
-	br = ncalloc(sizeof(*br));
+	br = hcalloc(sizeof(*br));
 	br->state = st;
 	br->actions = newlinklist();
 	addlinknode(result->out, br);
@@ -948,7 +936,7 @@
 
     while (1) {
 	if ((s = *rparseargs) && s[0] == '{' && s[(l = strlen(s)) - 1] == '}') {
-	    char *action = ncalloc(l - 1);
+	    char *action = hcalloc(l - 1);
 	    LinkNode ln;
 
 	    rparseargs++;
@@ -1136,22 +1124,21 @@
     opts[EXTENDEDGLOB] = 1;
 
     rparseargs = args + 3;
-    HEAPALLOC {
-	pushheap();
-        rparsestates = newlinklist();
-	if (setjmp(rparseerr) || rparsealt(&result, &rparseerr) || *rparseargs) {
-	    if (*rparseargs)
-		zwarnnam(nam, "invalid regex : %s", *rparseargs, 0);
-	    else
-		zwarnnam(nam, "not enough regex arguments", NULL, 0);
-	    ret = 3;
-	} else
-	    ret = 0;
 
-	if (!ret)
-	    ret = rmatch(&result, subj, var1, var2, ops['c']);
-        popheap();
-    } LASTALLOC;
+    pushheap();
+    rparsestates = newlinklist();
+    if (setjmp(rparseerr) || rparsealt(&result, &rparseerr) || *rparseargs) {
+	if (*rparseargs)
+	    zwarnnam(nam, "invalid regex : %s", *rparseargs, 0);
+	else
+	    zwarnnam(nam, "not enough regex arguments", NULL, 0);
+	ret = 3;
+    } else
+	ret = 0;
+
+    if (!ret)
+	ret = rmatch(&result, subj, var1, var2, ops['c']);
+    popheap();
 
     opts[EXTENDEDGLOB] = oldextendedglob;
     return ret;
@@ -1511,10 +1498,7 @@
 	sethparam(assoc, aval);
     }
     if (del) {
-	PERMALLOC {
-	    pp = arrdup(pp);
-	} LASTALLOC;
-
+	pp = zarrdup(pp);
 	freearray(pparams);
 	pparams = pp;
     }
diff -ru ../z.old/Src/Zle/compcore.c Src/Zle/compcore.c
--- ../z.old/Src/Zle/compcore.c	Wed Feb 23 14:22:06 2000
+++ Src/Zle/compcore.c	Wed Feb 23 14:23:53 2000
@@ -262,167 +262,164 @@
 {
     int ret = 0, lst = dat->lst, incmd = dat->incmd;
     char *s = dat->s;
+    char *opm;
+    LinkNode n;
 
-    HEAPALLOC {
-	char *opm;
-	LinkNode n;
+    pushheap();
 
-	pushheap();
+    ainfo = fainfo = NULL;
+    matchers = newlinklist();
 
-	ainfo = fainfo = NULL;
-	matchers = newlinklist();
+    zsfree(compqstack);
+    compqstack = ztrdup("\\");
+    if (instring == 2)
+	compqstack[0] = '"';
+    else if (instring)
+	compqstack[0] = '\'';
+
+    hasunqu = 0;
+    useline = (lst != COMP_LIST_COMPLETE);
+    useexact = isset(RECEXACT);
+    zsfree(compexactstr);
+    compexactstr = ztrdup("");
+    uselist = (useline ?
+	       ((isset(AUTOLIST) && !isset(BASHAUTOLIST)) ? 
+		(isset(LISTAMBIGUOUS) ? 3 : 2) : 0) : 1);
+    zsfree(comppatmatch);
+    opm = comppatmatch = ztrdup(useglob ? "*" : "");
+    zsfree(comppatinsert);
+    comppatinsert = ztrdup("menu");
+    forcelist = 0;
+    haspattern = 0;
+    complistmax = getiparam("LISTMAX");
+    zsfree(complastprompt);
+    complastprompt = ztrdup(((isset(ALWAYSLASTPROMPT) && zmult == 1) ||
+			     (unset(ALWAYSLASTPROMPT) && zmult != 1)) ?
+			    "yes" : "");
+    dolastprompt = 1;
+    zsfree(complist);
+    complist = ztrdup(isset(LISTROWSFIRST) ?
+		      (isset(LISTPACKED) ? "packed rows" : "rows") :
+		      (isset(LISTPACKED) ? "packed" : ""));
+    startauto = isset(AUTOMENU);
+    movetoend = ((cs == we || isset(ALWAYSTOEND)) ? 2 : 1);
+    showinglist = 0;
+    hasmatched = 0;
+    minmlen = 1000000;
+    maxmlen = -1;
+
+    /* Make sure we have the completion list and compctl. */
+    if (makecomplist(s, incmd, lst)) {
+	/* Error condition: feeeeeeeeeeeeep(). */
+	cs = 0;
+	foredel(ll);
+	inststr(origline);
+	cs = origcs;
+	clearlist = 1;
+	ret = 1;
+	minfo.cur = NULL;
+	goto compend;
+    }
+    zsfree(lastprebr);
+    zsfree(lastpostbr);
+    lastprebr = lastpostbr = NULL;
+
+    if (comppatmatch && *comppatmatch && comppatmatch != opm)
+	haspattern = 1;
+    if (!useline && uselist) {
+	/* All this and the guy only wants to see the list, sigh. */
+	cs = 0;
+	foredel(ll);
+	inststr(origline);
+	cs = origcs;
+	showinglist = -2;
+    } else if (useline == 2 && nmatches > 1) {
+	int first = 1, nm = nmatches;
+	Cmatch *mc;
 
-	zsfree(compqstack);
-	compqstack = ztrdup("\\");
-	if (instring == 2)
-	    compqstack[0] = '"';
-	else if (instring)
-	    compqstack[0] = '\'';
-
-	hasunqu = 0;
-	useline = (lst != COMP_LIST_COMPLETE);
-	useexact = isset(RECEXACT);
-	zsfree(compexactstr);
-	compexactstr = ztrdup("");
-	uselist = (useline ?
-		   ((isset(AUTOLIST) && !isset(BASHAUTOLIST)) ? 
-		    (isset(LISTAMBIGUOUS) ? 3 : 2) : 0) : 1);
-	zsfree(comppatmatch);
-	opm = comppatmatch = ztrdup(useglob ? "*" : "");
-	zsfree(comppatinsert);
-	comppatinsert = ztrdup("menu");
-	forcelist = 0;
-	haspattern = 0;
-	complistmax = getiparam("LISTMAX");
-	zsfree(complastprompt);
-	complastprompt = ztrdup(((isset(ALWAYSLASTPROMPT) && zmult == 1) ||
-				 (unset(ALWAYSLASTPROMPT) && zmult != 1)) ?
-				"yes" : "");
-	dolastprompt = 1;
-	zsfree(complist);
-	complist = ztrdup(isset(LISTROWSFIRST) ?
-			  (isset(LISTPACKED) ? "packed rows" : "rows") :
-			  (isset(LISTPACKED) ? "packed" : ""));
-	startauto = isset(AUTOMENU);
-	movetoend = ((cs == we || isset(ALWAYSTOEND)) ? 2 : 1);
-	showinglist = 0;
-	hasmatched = 0;
-	minmlen = 1000000;
-	maxmlen = -1;
-
-	/* Make sure we have the completion list and compctl. */
-	if (makecomplist(s, incmd, lst)) {
-	    /* Error condition: feeeeeeeeeeeeep(). */
-	    cs = 0;
-	    foredel(ll);
-	    inststr(origline);
-	    cs = origcs;
-	    clearlist = 1;
-	    ret = 1;
-	    minfo.cur = NULL;
-	    goto compend;
-	}
-	zsfree(lastprebr);
-	zsfree(lastpostbr);
-	lastprebr = lastpostbr = NULL;
-
-	if (comppatmatch && *comppatmatch && comppatmatch != opm)
-	    haspattern = 1;
-	if (!useline && uselist) {
-	    /* All this and the guy only wants to see the list, sigh. */
-	    cs = 0;
-	    foredel(ll);
-	    inststr(origline);
-	    cs = origcs;
-	    showinglist = -2;
-	} else if (useline == 2 && nmatches > 1) {
-	    int first = 1, nm = nmatches;
-	    Cmatch *mc;
-
-	    menucmp = 1;
-	    menuacc = 0;
-
-	    for (minfo.group = amatches;
-		 minfo.group && !(minfo.group)->mcount;
-		 minfo.group = (minfo.group)->next);
-
-	    mc = (minfo.group)->matches;
-
-	    while (1) {
-		if (!first)
-		    accept_last();
-		first = 0;
-
-		if (!--nm)
-		    menucmp = 0;
-
-		do_single(*mc);
-		minfo.cur = mc;
-
-		if (!*++(minfo.cur)) {
-		    do {
-			if (!(minfo.group = (minfo.group)->next))
-			    break;
-		    } while (!(minfo.group)->mcount);
-		    if (!minfo.group)
+	menucmp = 1;
+	menuacc = 0;
+
+	for (minfo.group = amatches;
+	     minfo.group && !(minfo.group)->mcount;
+	     minfo.group = (minfo.group)->next);
+
+	mc = (minfo.group)->matches;
+
+	while (1) {
+	    if (!first)
+		accept_last();
+	    first = 0;
+
+	    if (!--nm)
+		menucmp = 0;
+
+	    do_single(*mc);
+	    minfo.cur = mc;
+
+	    if (!*++(minfo.cur)) {
+		do {
+		    if (!(minfo.group = (minfo.group)->next))
 			break;
-		    minfo.cur = minfo.group->matches;
-		}
-		mc = minfo.cur;
+		} while (!(minfo.group)->mcount);
+		if (!minfo.group)
+		    break;
+		minfo.cur = minfo.group->matches;
 	    }
-	    menucmp = 0;
-	    minfo.cur = NULL;
+	    mc = minfo.cur;
+	}
+	menucmp = 0;
+	minfo.cur = NULL;
 
-	    if (forcelist)
-		showinglist = -2;
-	    else
-		invalidatelist();
-	} else if (useline) {
-	    /* We have matches. */
-	    if (nmatches > 1) {
-		/* There is more than one match. */
-		ret = do_ambiguous();
-	    } else if (nmatches == 1) {
-		/* Only one match. */
-		Cmgroup m = amatches;
-
-		while (!m->mcount)
-		    m = m->next;
-		minfo.cur = NULL;
-		minfo.asked = 0;
-		do_single(m->matches[0]);
-		if (forcelist) {
-		    if (uselist)
-			showinglist = -2;
-		    else
-			clearlist = 1;
-		} else
-		    invalidatelist();
-	    }
-	} else {
-	    invalidatelist();
-	    if (forcelist)
-		clearlist = 1;
-	    cs = 0;
-	    foredel(ll);
-	    inststr(origline);
-	    cs = origcs;
-	}
-	/* Print the explanation strings if needed. */
-	if (!showinglist && validlist && usemenu != 2 && nmatches != 1 &&
-	    useline != 2 && (!oldlist || !listshown)) {
-	    onlyexpl = 1;
+	if (forcelist)
 	    showinglist = -2;
+	else
+	    invalidatelist();
+    } else if (useline) {
+	/* We have matches. */
+	if (nmatches > 1) {
+	    /* There is more than one match. */
+	    ret = do_ambiguous();
+	} else if (nmatches == 1) {
+	    /* Only one match. */
+	    Cmgroup m = amatches;
+
+	    while (!m->mcount)
+		m = m->next;
+	    minfo.cur = NULL;
+	    minfo.asked = 0;
+	    do_single(m->matches[0]);
+	    if (forcelist) {
+		if (uselist)
+		    showinglist = -2;
+		else
+		    clearlist = 1;
+	    } else
+		invalidatelist();
 	}
-      compend:
-	for (n = firstnode(matchers); n; incnode(n))
-	    freecmatcher((Cmatcher) getdata(n));
-
-	ll = strlen((char *)line);
-	if (cs > ll)
-	    cs = ll;
-	popheap();
-    } LASTALLOC;
+    } else {
+	invalidatelist();
+	if (forcelist)
+	    clearlist = 1;
+	cs = 0;
+	foredel(ll);
+	inststr(origline);
+	cs = origcs;
+    }
+    /* Print the explanation strings if needed. */
+    if (!showinglist && validlist && usemenu != 2 && nmatches != 1 &&
+	useline != 2 && (!oldlist || !listshown)) {
+	onlyexpl = 1;
+	showinglist = -2;
+    }
+ compend:
+    for (n = firstnode(matchers); n; incnode(n))
+	freecmatcher((Cmatcher) getdata(n));
+
+    ll = strlen((char *)line);
+    if (cs > ll)
+	cs = ll;
+    popheap();
 
     return ret;
 }
@@ -581,16 +578,11 @@
 	if (usea && (!aadd || clwords[0])) {
 	    char **q;
 
-	    PERMALLOC {
-		q = compwords = (char **)
-		    zalloc((clwnum + 1) * sizeof(char *));
-		for (p = clwords + aadd; *p; p++, q++) {
-		    tmp = dupstring(*p);
-		    untokenize(tmp);
-		    *q = ztrdup(tmp);
-		}
-		*q = NULL;
-	    } LASTALLOC;
+	    q = compwords = (char **)
+		zalloc((clwnum + 1) * sizeof(char *));
+	    for (p = clwords + aadd; *p; p++, q++)
+		untokenize(*q = ztrdup(*p));
+	    *q = NULL;
 	} else
 	    compwords = (char **) zcalloc(sizeof(char *));
 
@@ -861,16 +853,14 @@
 
 	    return 0;
 	}
-	PERMALLOC {
-	    if (lastmatches) {
-		freematches(lastmatches);
-		lastmatches = NULL;
-	    }
-	    permmatches(1);
-	    amatches = pmatches;
-	    lastpermmnum = permmnum;
-	    lastpermgnum = permgnum;
-	} LASTALLOC;
+	if (lastmatches) {
+	    freematches(lastmatches);
+	    lastmatches = NULL;
+	}
+	permmatches(1);
+	amatches = pmatches;
+	lastpermmnum = permmnum;
+	lastpermgnum = permgnum;
 
 	lastmatches = pmatches;
 	lastlmatches = lmatches;
@@ -1484,19 +1474,17 @@
 
     if (!*argv) {
 	SWITCHHEAPS(compheap) {
-	    HEAPALLOC {
-		/* Select the group in which to store the matches. */
-		gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT  : 0) |
-			  ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) |
-			  ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0));
-		if (dat->group) {
-		    endcmgroup(NULL);
-		    begcmgroup(dat->group, gflags);
-		} else {
-		    endcmgroup(NULL);
-		    begcmgroup("default", 0);
-		}
-	    } LASTALLOC;
+	    /* Select the group in which to store the matches. */
+	    gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT  : 0) |
+		      ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) |
+		      ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0));
+	    if (dat->group) {
+		endcmgroup(NULL);
+		begcmgroup(dat->group, gflags);
+	    } else {
+		endcmgroup(NULL);
+		begcmgroup("default", 0);
+	    }
 	} SWITCHBACKHEAPS;
 
 	return 1;
@@ -1534,349 +1522,344 @@
     /* Switch back to the heap that was used when the completion widget
      * was invoked. */
     SWITCHHEAPS(compheap) {
-	HEAPALLOC {
-	    if ((doadd = (!dat->apar && !dat->opar && !dat->dpar)) &&
-		(dat->aflags & CAF_MATCH))
-		hasmatched = 1;
-	    if (dat->apar)
-		aparl = newlinklist();
-	    if (dat->opar)
-		oparl = newlinklist();
-	    if (dat->dpar) {
-		if (*(dat->dpar) == '(')
-		    dparr = NULL;
-		else if ((dparr = get_user_var(dat->dpar)) && !*dparr)
-		    dparr = NULL;
-		dparl = newlinklist();
-	    }
-	    if (dat->exp) {
-		curexpl = (Cexpl) zhalloc(sizeof(struct cexpl));
-		curexpl->count = curexpl->fcount = 0;
-		curexpl->str = dupstring(dat->exp);
-	    } else
-		curexpl = NULL;
+	if ((doadd = (!dat->apar && !dat->opar && !dat->dpar)) &&
+	    (dat->aflags & CAF_MATCH))
+	    hasmatched = 1;
+	if (dat->apar)
+	    aparl = newlinklist();
+	if (dat->opar)
+	    oparl = newlinklist();
+	if (dat->dpar) {
+	    if (*(dat->dpar) == '(')
+		dparr = NULL;
+	    else if ((dparr = get_user_var(dat->dpar)) && !*dparr)
+		dparr = NULL;
+	    dparl = newlinklist();
+	}
+	if (dat->exp) {
+	    curexpl = (Cexpl) zhalloc(sizeof(struct cexpl));
+	    curexpl->count = curexpl->fcount = 0;
+	    curexpl->str = dupstring(dat->exp);
+	} else
+	    curexpl = NULL;
 
-	    /* Store the matcher in our stack of matchers. */
-	    if (dat->match) {
-		mst.next = mstack;
-		mst.matcher = dat->match;
-		mstack = &mst;
-
-		add_bmatchers(dat->match);
-
-		addlinknode(matchers, dat->match);
-		dat->match->refc++;
-	    }
-	    if (mnum && (mstack || bmatchers))
-		update_bmatchers();
-
-	    /* Get the suffixes to ignore. */
-	    if (dat->ign && (aign = get_user_var(dat->ign))) {
-		char **ap, **sp, *tmp;
-		Patprog *pp, prog;
-
-		pign = (Patprog *) zhalloc((arrlen(aign) + 1) * sizeof(Patprog));
-
-		for (ap = sp = aign, pp = pign; (tmp = *ap); ap++) {
-		    tokenize(tmp);
-		    remnulargs(tmp);
-		    if (((tmp[0] == Quest && tmp[1] == Star) ||
-			 (tmp[1] == Quest && tmp[0] == Star)) &&
-			tmp[2] && !haswilds(tmp + 2))
-			untokenize(*sp++ = tmp + 2);
-		    else if ((prog = patcompile(tmp, 0, NULL)))
-			*pp++ = prog;
-		}
-		*sp = NULL;
-		*pp = NULL;
-		if (!*aign)
-		    aign = NULL;
-		if (!*pign)
-		    pign = NULL;
-	    }
-	    /* Get the display strings. */
-	    if (dat->disp)
-		if ((disp = get_user_var(dat->disp)))
-		    disp--;
-	    /* Get the contents of the completion variables if we have
-	     * to perform matching. */
-	    if (dat->aflags & CAF_MATCH) {
-		lipre = dupstring(compiprefix);
-		lisuf = dupstring(compisuffix);
-		lpre = dupstring(compprefix);
-		lsuf = dupstring(compsuffix);
-		llpl = strlen(lpre);
-		llsl = strlen(lsuf);
-		/* Test if there is an existing -P prefix. */
-		if (dat->pre && *dat->pre) {
-		    pl = pfxlen(dat->pre, lpre);
-		    llpl -= pl;
-		    lpre += pl;
+	/* Store the matcher in our stack of matchers. */
+	if (dat->match) {
+	    mst.next = mstack;
+	    mst.matcher = dat->match;
+	    mstack = &mst;
+
+	    add_bmatchers(dat->match);
+
+	    addlinknode(matchers, dat->match);
+	    dat->match->refc++;
+	}
+	if (mnum && (mstack || bmatchers))
+	    update_bmatchers();
+
+	/* Get the suffixes to ignore. */
+	if (dat->ign && (aign = get_user_var(dat->ign))) {
+	    char **ap, **sp, *tmp;
+	    Patprog *pp, prog;
+
+	    pign = (Patprog *) zhalloc((arrlen(aign) + 1) * sizeof(Patprog));
+
+	    for (ap = sp = aign, pp = pign; (tmp = *ap); ap++) {
+		tokenize(tmp);
+		remnulargs(tmp);
+		if (((tmp[0] == Quest && tmp[1] == Star) ||
+		     (tmp[1] == Quest && tmp[0] == Star)) &&
+		    tmp[2] && !haswilds(tmp + 2))
+		    untokenize(*sp++ = tmp + 2);
+		else if ((prog = patcompile(tmp, 0, NULL)))
+		    *pp++ = prog;
+	    }
+	    *sp = NULL;
+	    *pp = NULL;
+	    if (!*aign)
+		aign = NULL;
+	    if (!*pign)
+		pign = NULL;
+	}
+	/* Get the display strings. */
+	if (dat->disp)
+	    if ((disp = get_user_var(dat->disp)))
+		disp--;
+	/* Get the contents of the completion variables if we have
+	 * to perform matching. */
+	if (dat->aflags & CAF_MATCH) {
+	    lipre = dupstring(compiprefix);
+	    lisuf = dupstring(compisuffix);
+	    lpre = dupstring(compprefix);
+	    lsuf = dupstring(compsuffix);
+	    llpl = strlen(lpre);
+	    llsl = strlen(lsuf);
+	    /* Test if there is an existing -P prefix. */
+	    if (dat->pre && *dat->pre) {
+		pl = pfxlen(dat->pre, lpre);
+		llpl -= pl;
+		lpre += pl;
+	    }
+	}
+	/* Now duplicate the strings we have from the command line. */
+	if (dat->ipre)
+	    dat->ipre = (lipre ? dyncat(lipre, dat->ipre) :
+			 dupstring(dat->ipre));
+	else if (lipre)
+	    dat->ipre = lipre;
+	if (dat->isuf)
+	    dat->isuf = (lisuf ? dyncat(lisuf, dat->isuf) :
+			 dupstring(dat->isuf));
+	else if (lisuf)
+	    dat->isuf = lisuf;
+	if (dat->ppre) {
+	    dat->ppre = ((dat->flags & CMF_FILE) ?
+			 tildequote(dat->ppre, !!(dat->aflags & CAF_QUOTE)) :
+			 multiquote(dat->ppre, !!(dat->aflags & CAF_QUOTE)));
+	    lpl = strlen(dat->ppre);
+	} else
+	    lpl = 0;
+	if (dat->psuf) {
+	    dat->psuf = multiquote(dat->psuf, !!(dat->aflags & CAF_QUOTE));
+	    lsl = strlen(dat->psuf);
+	} else
+	    lsl = 0;
+	if (dat->aflags & CAF_MATCH) {
+	    int ml, gfl = 0;
+	    char *globflag = NULL;
+
+	    if (comppatmatch && *comppatmatch &&
+		dat->ppre && lpre[0] == '(' && lpre[1] == '#') {
+		char *p;
+
+		for (p = lpre + 2; *p && *p != ')'; p++);
+
+		if (*p == ')') {
+		    char sav = p[1];
+
+		    p[1] = '\0';
+		    globflag = dupstring(lpre);
+		    gfl = p - lpre + 1;
+		    p[1] = sav;
+
+		    lpre = p + 1;
+		    llpl -= gfl;
 		}
 	    }
-	    /* Now duplicate the strings we have from the command line. */
-	    if (dat->ipre)
-		dat->ipre = (lipre ? dyncat(lipre, dat->ipre) :
-			     dupstring(dat->ipre));
-	    else if (lipre)
-		dat->ipre = lipre;
-	    if (dat->isuf)
-		dat->isuf = (lisuf ? dyncat(lisuf, dat->isuf) :
-			     dupstring(dat->isuf));
-	    else if (lisuf)
-		dat->isuf = lisuf;
-	    if (dat->ppre) {
-		dat->ppre = ((dat->flags & CMF_FILE) ?
-			     tildequote(dat->ppre,
-					!!(dat->aflags & CAF_QUOTE)) :
-			     multiquote(dat->ppre,
-					!!(dat->aflags & CAF_QUOTE)));
-		lpl = strlen(dat->ppre);
-	    } else
-		lpl = 0;
-	    if (dat->psuf) {
-		dat->psuf = multiquote(dat->psuf, !!(dat->aflags & CAF_QUOTE));
-		lsl = strlen(dat->psuf);
-	    } else
-		lsl = 0;
-	    if (dat->aflags & CAF_MATCH) {
-		int ml, gfl = 0;
-		char *globflag = NULL;
-
-		if (comppatmatch && *comppatmatch &&
-		    dat->ppre && lpre[0] == '(' && lpre[1] == '#') {
-		    char *p;
-
-		    for (p = lpre + 2; *p && *p != ')'; p++);
-
-		    if (*p == ')') {
-			char sav = p[1];
-
-			p[1] = '\0';
-			globflag = dupstring(lpre);
-			gfl = p - lpre + 1;
-			p[1] = sav;
+	    s = dat->ppre ? dat->ppre : "";
+	    if ((ml = match_str(lpre, s, &bpl, 0, NULL, 0, 0, 1)) >= 0) {
+		if (matchsubs) {
+		    Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, 0);
 
-			lpre = p + 1;
-			llpl -= gfl;
-		    }
-		}
-		s = dat->ppre ? dat->ppre : "";
-		if ((ml = match_str(lpre, s, &bpl, 0, NULL, 0, 0, 1)) >= 0) {
-		    if (matchsubs) {
-			Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, 0);
-
-			tmp->prefix = matchsubs;
-			if (matchlastpart)
-			    matchlastpart->next = tmp;
-			else
-			    matchparts = tmp;
-		    }
-		    pline = matchparts;
-		    lpre += ml;
-		    llpl -= ml;
-		    bcp = ml;
-		    bpadd = strlen(s) - ml;
-		} else {
-		    if (llpl <= lpl && strpfx(lpre, s))
-			lpre = "";
-		    else if (llpl > lpl && strpfx(s, lpre))
-			lpre += lpl;
+		    tmp->prefix = matchsubs;
+		    if (matchlastpart)
+			matchlastpart->next = tmp;
 		    else
-			*argv = NULL;
-		    bcp = lpl;
+			matchparts = tmp;
 		}
-		s = dat->psuf ? dat->psuf : "";
-		if ((ml = match_str(lsuf, s, &bsl, 0, NULL, 1, 0, 1)) >= 0) {
-		    if (matchsubs) {
-			Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0,
-					      CLF_SUF);
-
-			tmp->suffix = matchsubs;
-			if (matchlastpart)
-			    matchlastpart->next = tmp;
-			else
-			    matchparts = tmp;
-		    }
-		    sline = revert_cline(matchparts);
-		    lsuf[llsl - ml] = '\0';
-		    llsl -= ml;
-		    bcs = ml;
-		    bsadd = strlen(s) - ml;
-		} else {
-		    if (llsl <= lsl && strsfx(lsuf, s))
-			lsuf = "";
-		    else if (llsl > lsl && strsfx(s, lsuf))
-			lsuf[llsl - lsl] = '\0';
+		pline = matchparts;
+		lpre += ml;
+		llpl -= ml;
+		bcp = ml;
+		bpadd = strlen(s) - ml;
+	    } else {
+		if (llpl <= lpl && strpfx(lpre, s))
+		    lpre = "";
+		else if (llpl > lpl && strpfx(s, lpre))
+		    lpre += lpl;
+		else
+		    *argv = NULL;
+		bcp = lpl;
+	    }
+	    s = dat->psuf ? dat->psuf : "";
+	    if ((ml = match_str(lsuf, s, &bsl, 0, NULL, 1, 0, 1)) >= 0) {
+		if (matchsubs) {
+		    Cline tmp = get_cline(NULL, 0, NULL, 0, NULL, 0, CLF_SUF);
+
+		    tmp->suffix = matchsubs;
+		    if (matchlastpart)
+			matchlastpart->next = tmp;
 		    else
-			*argv = NULL;
-		    bcs = lsl;
+			matchparts = tmp;
 		}
-		if (comppatmatch && *comppatmatch) {
-		    int is = (*comppatmatch == '*');
-		    char *tmp = (char *) zhalloc(2 + llpl + llsl + gfl);
-
-		    if (gfl) {
-			strcpy(tmp, globflag);
-			strcat(tmp, lpre);
-		    } else
-			strcpy(tmp, lpre);
-		    tmp[llpl + gfl] = 'x';
-		    strcpy(tmp + llpl + gfl + is, lsuf);
-
-		    tokenize(tmp);
-		    remnulargs(tmp);
-		    if (haswilds(tmp)) {
-			if (is)
-			    tmp[llpl + gfl] = Star;
-			if ((cp = patcompile(tmp, 0, NULL)))
-			    haspattern = 1;
-		    }
-		}
-	    }
-	    /* Select the group in which to store the matches. */
-	    gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT  : 0) |
-		      ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) |
-		      ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0));
-	    if (dat->group) {
-		endcmgroup(NULL);
-		begcmgroup(dat->group, gflags);
+		sline = revert_cline(matchparts);
+		lsuf[llsl - ml] = '\0';
+		llsl -= ml;
+		bcs = ml;
+		bsadd = strlen(s) - ml;
 	    } else {
-		endcmgroup(NULL);
-		begcmgroup("default", 0);
+		if (llsl <= lsl && strsfx(lsuf, s))
+		    lsuf = "";
+		else if (llsl > lsl && strsfx(s, lsuf))
+		    lsuf[llsl - lsl] = '\0';
+		else
+		    *argv = NULL;
+		bcs = lsl;
 	    }
-	    if (*argv) {
-		if (dat->pre)
-		    dat->pre = dupstring(dat->pre);
-		if (dat->suf)
-		    dat->suf = dupstring(dat->suf);
-		if (!dat->prpre && (dat->prpre = oppre)) {
-		    singsub(&(dat->prpre));
-		    untokenize(dat->prpre);
+	    if (comppatmatch && *comppatmatch) {
+		int is = (*comppatmatch == '*');
+		char *tmp = (char *) zhalloc(2 + llpl + llsl + gfl);
+
+		if (gfl) {
+		    strcpy(tmp, globflag);
+		    strcat(tmp, lpre);
 		} else
-		    dat->prpre = dupstring(dat->prpre);
-		/* Select the set of matches. */
-		oisalt = (dat->aflags & CAF_ALT);
-
-		if (dat->remf) {
-		    dat->remf = dupstring(dat->remf);
-		    dat->rems = NULL;
-		} else if (dat->rems)
-		    dat->rems = dupstring(dat->rems);
-
-		if (lpre)
-		    lpre = ((!(dat->aflags & CAF_QUOTE) &&
-			     (!dat->ppre && (dat->flags & CMF_FILE))) ?
-			    tildequote(lpre, 1) : multiquote(lpre, 1));
-		if (lsuf)
-		    lsuf = multiquote(lsuf, 1);
-	    }
-	    /* Walk through the matches given. */
-	    obpl = bpl;
-	    obsl = bsl;
-	    if (!oisalt && (aign || pign)) {
-		int max = 0;
-		char **ap = argv;
-
-		ppl = (dat->ppre ? strlen(dat->ppre) : 0);
-		while ((s = *ap++))
-		    if ((sl = strlen(s)) > max)
-			max = sl;
-		psl = (dat->psuf ? strlen(dat->psuf) : 0);
-		ibuf = (char *) zhalloc(1 + ppl + max + psl);
-	    }
-	    for (; (s = *argv); argv++) {
-		bpl = obpl;
-		bsl = obsl;
-		if (disp) {
-		    if (!*++disp)
-			disp = NULL;
+		    strcpy(tmp, lpre);
+		tmp[llpl + gfl] = 'x';
+		strcpy(tmp + llpl + gfl + is, lsuf);
+
+		tokenize(tmp);
+		remnulargs(tmp);
+		if (haswilds(tmp)) {
+		    if (is)
+			tmp[llpl + gfl] = Star;
+		    if ((cp = patcompile(tmp, 0, NULL)))
+			haspattern = 1;
 		}
-		sl = strlen(s);
-		isalt = oisalt;
-		if (!isalt && (aign || pign)) {
-		    int il = ppl + sl + psl;
-
-		    if (ppl)
-			memcpy(ibuf, dat->ppre, ppl);
-		    strcpy(ibuf + ppl, s);
-		    if (psl)
-			strcpy(ibuf + ppl + sl, dat->psuf);
-
-		    if (aign) {
-			/* Do the suffix-test. If the match has one of the
-			 * suffixes from aign, we put it in the alternate set. */
-			char **pt = aign;
-			int filell;
-
-			for (isalt = 0; !isalt && *pt; pt++)
-			    isalt = ((filell = strlen(*pt)) < il &&
-				     !strcmp(*pt, ibuf + il - filell));
-		    }
-		    if (!isalt && pign) {
-			Patprog *pt = pign;
+	    }
+	}
+	/* Select the group in which to store the matches. */
+	gflags = (((dat->aflags & CAF_NOSORT ) ? CGF_NOSORT  : 0) |
+		  ((dat->aflags & CAF_UNIQALL) ? CGF_UNIQALL : 0) |
+		  ((dat->aflags & CAF_UNIQCON) ? CGF_UNIQCON : 0));
+	if (dat->group) {
+	    endcmgroup(NULL);
+	    begcmgroup(dat->group, gflags);
+	} else {
+	    endcmgroup(NULL);
+	    begcmgroup("default", 0);
+	}
+	if (*argv) {
+	    if (dat->pre)
+		dat->pre = dupstring(dat->pre);
+	    if (dat->suf)
+		dat->suf = dupstring(dat->suf);
+	    if (!dat->prpre && (dat->prpre = oppre)) {
+		singsub(&(dat->prpre));
+		untokenize(dat->prpre);
+	    } else
+		dat->prpre = dupstring(dat->prpre);
+	    /* Select the set of matches. */
+	    oisalt = (dat->aflags & CAF_ALT);
+
+	    if (dat->remf) {
+		dat->remf = dupstring(dat->remf);
+		dat->rems = NULL;
+	    } else if (dat->rems)
+		dat->rems = dupstring(dat->rems);
+
+	    if (lpre)
+		lpre = ((!(dat->aflags & CAF_QUOTE) &&
+			 (!dat->ppre && (dat->flags & CMF_FILE))) ?
+			tildequote(lpre, 1) : multiquote(lpre, 1));
+	    if (lsuf)
+		lsuf = multiquote(lsuf, 1);
+	}
+	/* Walk through the matches given. */
+	obpl = bpl;
+	obsl = bsl;
+	if (!oisalt && (aign || pign)) {
+	    int max = 0;
+	    char **ap = argv;
+
+	    ppl = (dat->ppre ? strlen(dat->ppre) : 0);
+	    while ((s = *ap++))
+		if ((sl = strlen(s)) > max)
+		    max = sl;
+	    psl = (dat->psuf ? strlen(dat->psuf) : 0);
+	    ibuf = (char *) zhalloc(1 + ppl + max + psl);
+	}
+	for (; (s = *argv); argv++) {
+	    bpl = obpl;
+	    bsl = obsl;
+	    if (disp) {
+		if (!*++disp)
+		    disp = NULL;
+	    }
+	    sl = strlen(s);
+	    isalt = oisalt;
+	    if (!isalt && (aign || pign)) {
+		int il = ppl + sl + psl;
+
+		if (ppl)
+		    memcpy(ibuf, dat->ppre, ppl);
+		strcpy(ibuf + ppl, s);
+		if (psl)
+		    strcpy(ibuf + ppl + sl, dat->psuf);
+
+		if (aign) {
+		    /* Do the suffix-test. If the match has one of the
+		     * suffixes from aign, we put it in the alternate set. */
+		    char **pt = aign;
+		    int filell;
+
+		    for (isalt = 0; !isalt && *pt; pt++)
+			isalt = ((filell = strlen(*pt)) < il &&
+				 !strcmp(*pt, ibuf + il - filell));
+		}
+		if (!isalt && pign) {
+		    Patprog *pt = pign;
+
+		    for (isalt = 0; !isalt && *pt; pt++)
+			isalt = pattry(*pt, ibuf);
+		}
+	    }
+	    if (!(dat->aflags & CAF_MATCH)) {
+		if (dat->aflags & CAF_QUOTE)
+		    ms = dupstring(s);
+		else
+		    sl = strlen(ms = multiquote(s, 0));
+		lc = bld_parts(ms, sl, -1, NULL);
+		isexact = 0;
+	    } else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc,
+					 (!(dat->aflags & CAF_QUOTE) ?
+					  (dat->ppre ||
+					   !(dat->flags & CMF_FILE) ? 1 : 2) : 0),
+					 &bpl, bcp, &bsl, bcs,
+					 &isexact))) {
+		if (dparr && !*++dparr)
+		    dparr = NULL;
+		continue;
+	    }
+	    if (doadd) {
+		Brinfo bp;
 
-			for (isalt = 0; !isalt && *pt; pt++)
-			    isalt = pattry(*pt, ibuf);
-		    }
+		for (bp = obpl; bp; bp = bp->next)
+		    bp->curpos += bpadd;
+		for (bp = obsl; bp; bp = bp->next)
+		    bp->curpos += bsadd;
+
+		if ((cm = add_match_data(isalt, ms, lc, dat->ipre, NULL,
+					 dat->isuf, dat->pre, dat->prpre,
+					 dat->ppre, pline,
+					 dat->psuf, sline,
+					 dat->suf, dat->flags, isexact))) {
+		    cm->rems = dat->rems;
+		    cm->remf = dat->remf;
+		    if (disp)
+			cm->disp = dupstring(*disp);
 		}
-		if (!(dat->aflags & CAF_MATCH)) {
-		    if (dat->aflags & CAF_QUOTE)
-			ms = dupstring(s);
-		    else
-			sl = strlen(ms = multiquote(s, 0));
-		    lc = bld_parts(ms, sl, -1, NULL);
-		    isexact = 0;
-		} else if (!(ms = comp_match(lpre, lsuf, s, cp, &lc,
-					     (!(dat->aflags & CAF_QUOTE) ?
-					      (dat->ppre ||
-					       !(dat->flags & CMF_FILE) ? 1 : 2) : 0),
-					     &bpl, bcp, &bsl, bcs,
-					     &isexact))) {
-		    if (dparr && !*++dparr)
+	    } else {
+		if (dat->apar)
+		    addlinknode(aparl, ms);
+		if (dat->opar)
+		    addlinknode(oparl, s);
+		if (dat->dpar && dparr) {
+		    addlinknode(dparl, *dparr);
+		    if (!*++dparr)
 			dparr = NULL;
-		    continue;
-		}
-		if (doadd) {
-		    Brinfo bp;
-
-		    for (bp = obpl; bp; bp = bp->next)
-			bp->curpos += bpadd;
-		    for (bp = obsl; bp; bp = bp->next)
-			bp->curpos += bsadd;
-
-		    if ((cm = add_match_data(isalt, ms, lc, dat->ipre, NULL,
-					     dat->isuf, dat->pre, dat->prpre,
-					     dat->ppre, pline,
-					     dat->psuf, sline,
-					     dat->suf, dat->flags, isexact))) {
-			cm->rems = dat->rems;
-			cm->remf = dat->remf;
-			if (disp)
-			    cm->disp = dupstring(*disp);
-		    }
-		} else {
-		    if (dat->apar)
-			addlinknode(aparl, ms);
-		    if (dat->opar)
-			addlinknode(oparl, s);
-		    if (dat->dpar && dparr) {
-			addlinknode(dparl, *dparr);
-			if (!*++dparr)
-			    dparr = NULL;
-		    }
-		    free_cline(lc);
 		}
+		free_cline(lc);
 	    }
-	    if (dat->apar)
-		set_list_array(dat->apar, aparl);
-	    if (dat->opar)
-		set_list_array(dat->opar, oparl);
-	    if (dat->dpar)
-		set_list_array(dat->dpar, dparl);
-	    if (dat->exp)
-		addexpl();
-	} LASTALLOC;
+	}
+	if (dat->apar)
+	    set_list_array(dat->apar, aparl);
+	if (dat->opar)
+	    set_list_array(dat->opar, oparl);
+	if (dat->dpar)
+	    set_list_array(dat->dpar, dparl);
+	if (dat->exp)
+	    addexpl();
     } SWITCHBACKHEAPS;
 
     /* We switched back to the current heap, now restore the stack of
@@ -2379,7 +2362,7 @@
     int n, nl = 0, ll = 0;
 
     /* Build an array for the matches. */
-    rp = ap = (Cmatch *) ncalloc(((n = countlinknodes(l)) + 1) *
+    rp = ap = (Cmatch *) hcalloc(((n = countlinknodes(l)) + 1) *
 				 sizeof(Cmatch));
 
     /* And copy them into it. */
@@ -2487,7 +2470,7 @@
 {
     Cmatch r;
 
-    r = (Cmatch) ncalloc(sizeof(struct cmatch));
+    r = (Cmatch) zcalloc(sizeof(struct cmatch));
 
     r->str = ztrdup(m->str);
     r->ipre = ztrdup(m->ipre);
@@ -2522,7 +2505,7 @@
     r->autoq = ztrdup(m->autoq);
     r->qipl = m->qipl;
     r->qisl = m->qisl;
-    r->disp = dupstring(m->disp);
+    r->disp = ztrdup(m->disp);
 
     return r;
 }
@@ -2559,32 +2542,30 @@
 	fi = 1;
     }
     while (g) {
-	HEAPALLOC {
-	    if (fi)
-		/* We have no matches, try ignoring fignore. */
-		mlist = g->lfmatches;
-	    else
-		mlist = g->lmatches;
+	if (fi)
+	    /* We have no matches, try ignoring fignore. */
+	    mlist = g->lfmatches;
+	else
+	    mlist = g->lmatches;
 
-	    g->matches = makearray(mlist, 1, g->flags, &nn, &nl, &ll);
-	    g->mcount = nn;
-	    if ((g->lcount = nn - nl) < 0)
-		g->lcount = 0;
-	    g->llcount = ll;
-	    if (g->ylist) {
-		g->lcount = arrlen(g->ylist);
-		smatches = 2;
-	    }
-	    g->expls = (Cexpl *) makearray(g->lexpls, 0, 0, &(g->ecount),
-					   NULL, NULL);
+	g->matches = makearray(mlist, 1, g->flags, &nn, &nl, &ll);
+	g->mcount = nn;
+	if ((g->lcount = nn - nl) < 0)
+	    g->lcount = 0;
+	g->llcount = ll;
+	if (g->ylist) {
+	    g->lcount = arrlen(g->ylist);
+	    smatches = 2;
+	}
+	g->expls = (Cexpl *) makearray(g->lexpls, 0, 0, &(g->ecount),
+				       NULL, NULL);
 
-	    g->ccount = 0;
-	} LASTALLOC;
+	g->ccount = 0;
 
 	nmatches += g->mcount;
 	smatches += g->lcount;
 
-	n = (Cmgroup) ncalloc(sizeof(struct cmgroup));
+	n = (Cmgroup) zcalloc(sizeof(struct cmgroup));
 
 	if (!lmatches)
 	    lmatches = n;
@@ -2597,8 +2578,7 @@
 
 	n->flags = g->flags;
 	n->mcount = g->mcount;
-	n->matches = p = (Cmatch *) ncalloc((n->mcount + 1) *
-					    sizeof(Cmatch));
+	n->matches = p = (Cmatch *) zcalloc((n->mcount + 1) * sizeof(Cmatch));
 	n->name = ztrdup(g->name);
 	for (q = g->matches; *q; q++, p++)
 	    *p = dupmatch(*q, nbrbeg, nbrend);
@@ -2607,15 +2587,14 @@
 	n->lcount = g->lcount;
 	n->llcount = g->llcount;
 	if (g->ylist)
-	    n->ylist = arrdup(g->ylist);
+	    n->ylist = zarrdup(g->ylist);
 	else
 	    n->ylist = NULL;
 
 	if ((n->ecount = g->ecount)) {
-	    n->expls = ep = (Cexpl *) ncalloc((n->ecount + 1) *
-					      sizeof(Cexpl));
+	    n->expls = ep = (Cexpl *) zcalloc((n->ecount + 1) * sizeof(Cexpl));
 	    for (eq = g->expls; (o = *eq); eq++, ep++) {
-		*ep = e = (Cexpl) ncalloc(sizeof(struct cexpl));
+		*ep = e = (Cexpl) zcalloc(sizeof(struct cexpl));
 		e->count = (fi ? o->fcount : o->count);
 		e->str = ztrdup(o->str);
 	    }
diff -ru ../z.old/Src/Zle/compctl.c Src/Zle/compctl.c
--- ../z.old/Src/Zle/compctl.c	Wed Feb 23 14:22:07 2000
+++ Src/Zle/compctl.c	Wed Feb 23 14:23:53 2000
@@ -320,9 +320,7 @@
 	q = &(n->next);
     }
     freecmlist(cmatcher);
-    PERMALLOC {
-	cmatcher = cpcmlist(l);
-    } LASTALLOC;
+    cmatcher = cpcmlist(l);
 
     return 1;
 }
@@ -1254,9 +1252,7 @@
     cc->gname = ztrdup(cct->gname);
     cc->hpat = ztrdup(cct->hpat);
     cc->hnum = cct->hnum;
-    PERMALLOC {
-	cc->matcher = cpcmatcher(cct->matcher);
-    } LASTALLOC;
+    cc->matcher = cpcmatcher(cct->matcher);
     cc->mstr = ztrdup(cct->mstr);
 
     /* careful with extended completion:  it's already allocated */
@@ -1832,11 +1828,9 @@
 	    if (lastccused)
 		freelinklist(lastccused, (FreeFunc) freecompctl);
 
-	    PERMALLOC {
-		lastccused = newlinklist();
-		for (n = firstnode(ccused); n; incnode(n))
-		    addlinknode(lastccused, getdata(n));
-	    } LASTALLOC;
+	    lastccused = znewlinklist();
+	    for (n = firstnode(ccused); n; incnode(n))
+		zaddlinknode(lastccused, getdata(n));
 	} else if (ccused)
 	    for (n = firstnode(ccused); n; incnode(n))
 		if (((Compctl) getdata(n)) != &cc_dummy)
@@ -1857,16 +1851,14 @@
 	    dat->lst = 0;
 	    return 0;
 	}
-	PERMALLOC {
-	    if (lastmatches) {
-		freematches(lastmatches);
-		lastmatches = NULL;
-	    }
-	    permmatches(1);
-	    amatches = pmatches;
-	    lastpermmnum = permmnum;
-	    lastpermgnum = permgnum;
-	} LASTALLOC;
+	if (lastmatches) {
+	    freematches(lastmatches);
+	    lastmatches = NULL;
+	}
+	permmatches(1);
+	amatches = pmatches;
+	lastpermmnum = permmnum;
+	lastpermgnum = permgnum;
 
 	lastmatches = pmatches;
 	lastlmatches = lmatches;
@@ -2277,66 +2269,64 @@
 
     cdepth++;
     SWITCHHEAPS(compheap) {
-	HEAPALLOC {
-	    int ooffs = offs, lip, lp;
-	    char *str = comp_str(&lip, &lp, 0), *t;
-	    char *os = cmdstr, **ow = clwords, **p, **q, qc;
-	    int on = clwnum, op = clwpos, ois =  instring, oib = inbackt;
-	    char *oisuf = isuf, *oqp = qipre, *oqs = qisuf, *oaq = autoq;
-	    char buf[2];
-
-	    if (compquote && (qc = *compquote)) {
-		if (qc == '`') {
-		    instring = 0;
-		    inbackt = 0;
-		    autoq = "";
-		} else {
-		    buf[0] = qc;
-		    buf[1] = '\0';
-		    instring = (qc == '\'' ? 1 : 2);
-		    inbackt = 0;
-		    autoq = buf;
-		}
-	    } else {
-		instring = inbackt = 0;
+	int ooffs = offs, lip, lp;
+	char *str = comp_str(&lip, &lp, 0), *t;
+	char *os = cmdstr, **ow = clwords, **p, **q, qc;
+	int on = clwnum, op = clwpos, ois =  instring, oib = inbackt;
+	char *oisuf = isuf, *oqp = qipre, *oqs = qisuf, *oaq = autoq;
+	char buf[2];
+
+	if (compquote && (qc = *compquote)) {
+	    if (qc == '`') {
+		instring = 0;
+		inbackt = 0;
 		autoq = "";
+	    } else {
+		buf[0] = qc;
+		buf[1] = '\0';
+		instring = (qc == '\'' ? 1 : 2);
+		inbackt = 0;
+		autoq = buf;
 	    }
-	    qipre = ztrdup(compqiprefix ? compqiprefix : "");
-	    qisuf = ztrdup(compqisuffix ? compqisuffix : "");
-	    isuf = dupstring(compisuffix);
-	    ctokenize(isuf);
-	    remnulargs(isuf);
-	    clwnum = arrlen(compwords);
-	    clwpos = compcurrent - 1;
-	    cmdstr = ztrdup(compwords[0]);
-	    clwords = (char **) zalloc((clwnum + 1) * sizeof(char *));
-	    for (p = compwords, q = clwords; *p; p++, q++) {
-		t = dupstring(*p);
-		tokenize(t);
-		remnulargs(t);
-		*q = ztrdup(t);
-	    }
-	    *q = NULL;
-	    offs = lip + lp;
-	    incompfunc = 2;
-	    ret = makecomplistglobal(str, !clwpos, COMP_COMPLETE, flags);
-	    incompfunc = 1;
-	    isuf = oisuf;
-	    zsfree(qipre);
-	    zsfree(qisuf);
-	    qipre = oqp;
-	    qisuf = oqs;
-	    instring = ois;
-	    inbackt = oib;
-	    autoq = oaq;
-	    offs = ooffs;
-	    zsfree(cmdstr);
-	    freearray(clwords);
-	    cmdstr = os;
-	    clwords = ow;
-	    clwnum = on;
-	    clwpos = op;
-	} LASTALLOC;
+	} else {
+	    instring = inbackt = 0;
+	    autoq = "";
+	}
+	qipre = ztrdup(compqiprefix ? compqiprefix : "");
+	qisuf = ztrdup(compqisuffix ? compqisuffix : "");
+	isuf = dupstring(compisuffix);
+	ctokenize(isuf);
+	remnulargs(isuf);
+	clwnum = arrlen(compwords);
+	clwpos = compcurrent - 1;
+	cmdstr = ztrdup(compwords[0]);
+	clwords = (char **) zalloc((clwnum + 1) * sizeof(char *));
+	for (p = compwords, q = clwords; *p; p++, q++) {
+	    t = dupstring(*p);
+	    tokenize(t);
+	    remnulargs(t);
+	    *q = ztrdup(t);
+	}
+	*q = NULL;
+	offs = lip + lp;
+	incompfunc = 2;
+	ret = makecomplistglobal(str, !clwpos, COMP_COMPLETE, flags);
+	incompfunc = 1;
+	isuf = oisuf;
+	zsfree(qipre);
+	zsfree(qisuf);
+	qipre = oqp;
+	qisuf = oqs;
+	instring = ois;
+	inbackt = oib;
+	autoq = oaq;
+	offs = ooffs;
+	zsfree(cmdstr);
+	freearray(clwords);
+	cmdstr = os;
+	clwords = ow;
+	clwnum = on;
+	clwpos = op;
     } SWITCHBACKHEAPS;
     cdepth--;
 
@@ -2966,8 +2956,6 @@
 
     if (incompfunc != 1 && ccstack && findnode(ccstack, cc))
 	return;
-
-    MUSTUSEHEAP("complistflags");
 
     if (!ccstack)
 	ccstack = newlinklist();
diff -ru ../z.old/Src/Zle/complete.c Src/Zle/complete.c
--- ../z.old/Src/Zle/complete.c	Wed Feb 23 14:22:07 2000
+++ Src/Zle/complete.c	Wed Feb 23 14:23:53 2000
@@ -1172,10 +1172,7 @@
 	oqi = ztrdup(compquoting);
 	oqs = ztrdup(compqstack);
 	oaq = ztrdup(autoq);
-
-	PERMALLOC {
-	    owords = arrdup(compwords);
-	} LASTALLOC;
+	owords = zarrdup(compwords);
 
 	runshfunc(prog, w, name);
 
diff -ru ../z.old/Src/Zle/complist.c Src/Zle/complist.c
--- ../z.old/Src/Zle/complist.c	Wed Feb 23 14:22:07 2000
+++ Src/Zle/complist.c	Wed Feb 23 14:23:54 2000
@@ -864,331 +864,327 @@
     int i = 0, acc = 0, wishcol = 0, setwish = 0, oe = onlyexpl, wasnext = 0;
     char *s;
 
-    HEAPALLOC {
-	if (fdat || (dummy && (!(s = getsparam("SELECTMIN")) ||
-			       (dat && dat->num < atoi(s))))) {
-	    if (fdat) {
-		fdat->matches = dat->matches;
-		fdat->num = dat->num;
-	    }
-	    LASTALLOC_RETURN 0;
+    if (fdat || (dummy && (!(s = getsparam("SELECTMIN")) ||
+			   (dat && dat->num < atoi(s))))) {
+	if (fdat) {
+	    fdat->matches = dat->matches;
+	    fdat->num = dat->num;
 	}
-	fdat = dat;
-	selectlocalmap(mskeymap);
-	noselect = 0;
-	mselect = (*(minfo.cur))->gnum;
-	for (;;) {
-	    onlyexpl = 0;
-	    showinglist = -2;
-	    zrefresh();
-	    inselect = 1;
-	    if (noselect)
-		break;
-	    selected = 1;
-	    if (!i) {
-		i = mcols * mlines;
-		while (i--)
-		    if (mtab[i])
-			break;
-		if (!i)
+	return 0;
+    }
+    fdat = dat;
+    selectlocalmap(mskeymap);
+    noselect = 0;
+    mselect = (*(minfo.cur))->gnum;
+    for (;;) {
+	onlyexpl = 0;
+	showinglist = -2;
+	zrefresh();
+	inselect = 1;
+	if (noselect)
+	    break;
+	selected = 1;
+	if (!i) {
+	    i = mcols * mlines;
+	    while (i--)
+		if (mtab[i])
 		    break;
-		i = 1;
-	    }
-	    p = mmtabp;
-	    pg = mgtabp;
-	    minfo.cur = *p;
-	    minfo.group = *pg;
-	    if (setwish)
-		wishcol = mcol;
-	    else if (mcol > wishcol) {
-		while (mcol > 0 && p[-1] == minfo.cur)
-		    mcol--, p--, pg--;
-	    } else if (mcol < wishcol) {
-		while (mcol < mcols - 1 && p[1] == minfo.cur)
-		    mcol++, p++, pg++;
-	    }
-	    setwish = wasnext = 0;
+	    if (!i)
+		break;
+	    i = 1;
+	}
+	p = mmtabp;
+	pg = mgtabp;
+	minfo.cur = *p;
+	minfo.group = *pg;
+	if (setwish)
+	    wishcol = mcol;
+	else if (mcol > wishcol) {
+	    while (mcol > 0 && p[-1] == minfo.cur)
+		mcol--, p--, pg--;
+	} else if (mcol < wishcol) {
+	    while (mcol < mcols - 1 && p[1] == minfo.cur)
+		mcol++, p++, pg++;
+	}
+	setwish = wasnext = 0;
 
-	getk:
+    getk:
 
-	    if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak))
-		break;
-	    else if (cmd == Th(z_acceptline)) {
-		acc = 1;
+	if (!(cmd = getkeycmd()) || cmd == Th(z_sendbreak))
+	    break;
+	else if (cmd == Th(z_acceptline)) {
+	    acc = 1;
+	    break;
+	} else if (cmd == Th(z_acceptandinfernexthistory)) {
+	    Menustack s = (Menustack) zhalloc(sizeof(*s));
+
+	    s->prev = u;
+	    u = s;
+	    s->line = dupstring((char *) line);
+	    s->cs = cs;
+	    memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
+	    s->amatches = amatches;
+	    s->pmatches = pmatches;
+	    s->lastmatches = lastmatches;
+	    s->lastlmatches = lastlmatches;
+	    s->acc = menuacc;
+	    s->brbeg = dupbrinfo(brbeg, NULL, 1);
+	    s->brend = dupbrinfo(brend, NULL, 1);
+	    s->nbrbeg = nbrbeg;
+	    s->nbrend = nbrend;
+	    s->nmatches = nmatches;
+	    menucmp = menuacc = hasoldlist = 0;
+	    fixsuffix();
+	    validlist = 0;
+	    amatches = pmatches = lastmatches = NULL;
+	    invalidate_list();
+	    menucomplete(zlenoargs);
+	    if (dat->num < 2 || !minfo.cur || !*(minfo.cur)) {
+		noselect = clearlist = listshown = 1;
+		onlyexpl = 0;
+		zrefresh();
 		break;
-	    } else if (cmd == Th(z_acceptandinfernexthistory)) {
-		Menustack s = (Menustack) zhalloc(sizeof(*s));
-
-		s->prev = u;
-		u = s;
-		s->line = dupstring((char *) line);
-		s->cs = cs;
-		memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
-		s->amatches = amatches;
-		s->pmatches = pmatches;
-		s->lastmatches = lastmatches;
-		s->lastlmatches = lastlmatches;
-		s->acc = menuacc;
-		s->brbeg = dupbrinfo(brbeg, NULL);
-		s->brend = dupbrinfo(brend, NULL);
-		s->nbrbeg = nbrbeg;
-		s->nbrend = nbrend;
-		s->nmatches = nmatches;
-		menucmp = menuacc = hasoldlist = 0;
-		fixsuffix();
-		validlist = 0;
-		amatches = pmatches = lastmatches = NULL;
-		invalidate_list();
-		PERMALLOC {
-		    menucomplete(zlenoargs);
-		} LASTALLOC;
-		if (dat->num < 2 || !minfo.cur || !*(minfo.cur)) {
-		    noselect = clearlist = listshown = 1;
-		    onlyexpl = 0;
-		    zrefresh();
-		    break;
+	    }
+	    clearlist = listshown = 1;
+	    mselect = (*(minfo.cur))->gnum;
+	    setwish = wasnext = 1;
+	    continue;
+	} else if (cmd == Th(z_acceptandhold) ||
+		   cmd == Th(z_acceptandmenucomplete)) {
+	    Menustack s = (Menustack) zhalloc(sizeof(*s));
+
+	    s->prev = u;
+	    u = s;
+	    s->line = dupstring((char *) line);
+	    s->cs = cs;
+	    memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
+	    s->amatches = s->pmatches =
+		s->lastmatches = s->lastlmatches = NULL;
+	    s->acc = menuacc;
+	    s->brbeg = dupbrinfo(brbeg, NULL, 1);
+	    s->brend = dupbrinfo(brend, NULL, 1);
+	    s->nbrbeg = nbrbeg;
+	    s->nbrend = nbrend;
+	    s->nmatches = nmatches;
+	    accept_last();
+	    do_menucmp(0);
+	    mselect = (*(minfo.cur))->gnum;
+	    setwish = 1;
+	    continue;
+	} else if (cmd == Th(z_undo)) {
+	    int l;
+
+	    if (!u)
+		goto getk;
+
+	    cs = 0;
+	    foredel(ll);
+	    spaceinline(l = strlen(u->line));
+	    strncpy((char *) line, u->line, l);
+	    cs = u->cs;
+	    menuacc = u->acc;
+	    memcpy(&minfo, &(u->info), sizeof(struct menuinfo));
+	    p = &(minfo.cur);
+	    if (u->lastmatches && lastmatches != u->lastmatches) {
+		if (lastmatches)
+		    freematches(lastmatches);
+		amatches = u->amatches;
+		pmatches = u->pmatches;
+		lastmatches = u->lastmatches;
+		lastlmatches = u->lastlmatches;
+		nmatches = u->nmatches;
+		hasoldlist = 1;
+	    }
+	    freebrinfo(brbeg);
+	    freebrinfo(brend);
+	    brbeg = dupbrinfo(u->brbeg, &lastbrbeg, 0);
+	    brend = dupbrinfo(u->brend, &lastbrend, 0);
+	    nbrbeg = u->nbrbeg;
+	    nbrend = u->nbrend;
+
+	    u = u->prev;
+	    clearlist = 1;
+	    setwish = 1;
+	    listdat.valid = 0;
+	} else if (cmd == Th(z_redisplay)) {
+	    redisplay(zlenoargs);
+	    continue;
+	} else if (cmd == Th(z_clearscreen)) {
+	    clearscreen(zlenoargs);
+	    continue;
+	} else if (cmd == Th(z_downhistory) ||
+		   cmd == Th(z_downlineorhistory) ||
+		   cmd == Th(z_downlineorsearch) ||
+		   cmd == Th(z_vidownlineorhistory)) {
+	    do {
+		if (mline == mlines - 1) {
+		    p -= mline * mcols;
+		    mline = 0;
+		} else {
+		    mline++;
+		    p += mcols;
 		}
-		clearlist = listshown = 1;
-		mselect = (*(minfo.cur))->gnum;
-		setwish = wasnext = 1;
-		continue;
-	    } else if (cmd == Th(z_acceptandhold) ||
-		       cmd == Th(z_acceptandmenucomplete)) {
-		Menustack s = (Menustack) zhalloc(sizeof(*s));
-
-		s->prev = u;
-		u = s;
-		s->line = dupstring((char *) line);
-		s->cs = cs;
-		memcpy(&(s->info), &minfo, sizeof(struct menuinfo));
-		s->amatches = s->pmatches =
-		    s->lastmatches = s->lastlmatches = NULL;
-		s->acc = menuacc;
-		s->brbeg = dupbrinfo(brbeg, NULL);
-		s->brend = dupbrinfo(brend, NULL);
-		s->nbrbeg = nbrbeg;
-		s->nbrend = nbrend;
-		s->nmatches = nmatches;
-		accept_last();
-		do_menucmp(0);
-		mselect = (*(minfo.cur))->gnum;
-		setwish = 1;
-		continue;
-	    } else if (cmd == Th(z_undo)) {
-		int l;
-
-		if (!u)
-		    goto getk;
-
-		cs = 0;
-		foredel(ll);
-		spaceinline(l = strlen(u->line));
-		strncpy((char *) line, u->line, l);
-		cs = u->cs;
-		menuacc = u->acc;
-		memcpy(&minfo, &(u->info), sizeof(struct menuinfo));
-		p = &(minfo.cur);
-		if (u->lastmatches && lastmatches != u->lastmatches) {
-		    if (lastmatches)
-			freematches(lastmatches);
-		    amatches = u->amatches;
-		    pmatches = u->pmatches;
-		    lastmatches = u->lastmatches;
-		    lastlmatches = u->lastlmatches;
-		    nmatches = u->nmatches;
-		    hasoldlist = 1;
+		if (adjust_mcol(wishcol, &p, NULL))
+		    continue;
+	    } while (!*p);
+	} else if (cmd == Th(z_uphistory) ||
+		   cmd == Th(z_uplineorhistory) ||
+		   cmd == Th(z_uplineorsearch) ||
+		   cmd == Th(z_viuplineorhistory)) {
+	    do {
+		if (!mline) {
+		    mline = mlines - 1;
+		    p += mline * mcols;
+		} else {
+		    mline--;
+		    p -= mcols;
 		}
-		PERMALLOC {
-		    freebrinfo(brbeg);
-		    freebrinfo(brend);
-		    brbeg = dupbrinfo(u->brbeg, &lastbrbeg);
-		    brend = dupbrinfo(u->brend, &lastbrend);
-		    nbrbeg = u->nbrbeg;
-		    nbrend = u->nbrend;
-		} LASTALLOC;
-		u = u->prev;
-		clearlist = 1;
-		setwish = 1;
-		listdat.valid = 0;
-	    } else if (cmd == Th(z_redisplay)) {
-		redisplay(zlenoargs);
-		continue;
-	    } else if (cmd == Th(z_clearscreen)) {
-		clearscreen(zlenoargs);
-		continue;
-	    } else if (cmd == Th(z_downhistory) ||
-		       cmd == Th(z_downlineorhistory) ||
-		       cmd == Th(z_downlineorsearch) ||
-		       cmd == Th(z_vidownlineorhistory)) {
-		do {
-		    if (mline == mlines - 1) {
-			p -= mline * mcols;
-			mline = 0;
-		    } else {
-			mline++;
-			p += mcols;
-		    }
-		    if (adjust_mcol(wishcol, &p, NULL))
-			continue;
-		} while (!*p);
-	    } else if (cmd == Th(z_uphistory) ||
-		       cmd == Th(z_uplineorhistory) ||
-		       cmd == Th(z_uplineorsearch) ||
-		       cmd == Th(z_viuplineorhistory)) {
-		do {
-		    if (!mline) {
-			mline = mlines - 1;
-			p += mline * mcols;
-		    } else {
-			mline--;
-			p -= mcols;
-		    }
-		    if (adjust_mcol(wishcol, &p, NULL))
-			continue;
-		} while (!*p);
-	    } else if (cmd == Th(z_forwardchar) || cmd == Th(z_viforwardchar)) {
-		int omcol = mcol;
-		Cmatch *op = *p;
-
-		do {
-		    if (mcol == mcols - 1) {
-			p -= mcol;
-			mcol = 0;
-		    } else {
-			mcol++;
-			p++;
-		    }
-		} while (!*p || (mcol != omcol && *p == op));
-		wishcol = mcol;
-	    } else if (cmd == Th(z_backwardchar) || cmd == Th(z_vibackwardchar)) {
-		int omcol = mcol;
-		Cmatch *op = *p;
-
-		do {
-		    if (!mcol) {
-			mcol = mcols - 1;
-			p += mcol;
-		    } else {
-			mcol--;
-			p--;
-		    }
-		} while (!*p || (mcol != omcol && *p == op));
-		wishcol = mcol;
-	    } else if (cmd == Th(z_beginningofbufferorhistory) ||
-		       cmd == Th(z_beginningofline) ||
-		       cmd == Th(z_beginningoflinehist) ||
-		       cmd == Th(z_vibeginningofline)) {
-		p -= mcol;
-		mcol = 0;
-		while (!*p) {
+		if (adjust_mcol(wishcol, &p, NULL))
+		    continue;
+	    } while (!*p);
+	} else if (cmd == Th(z_forwardchar) || cmd == Th(z_viforwardchar)) {
+	    int omcol = mcol;
+	    Cmatch *op = *p;
+
+	    do {
+		if (mcol == mcols - 1) {
+		    p -= mcol;
+		    mcol = 0;
+		} else {
 		    mcol++;
 		    p++;
 		}
-		wishcol = 0;
-	    } else if (cmd == Th(z_endofbufferorhistory) ||
-		       cmd == Th(z_endofline) ||
-		       cmd == Th(z_endoflinehist) ||
-		       cmd == Th(z_viendofline)) {
-		p += mcols - mcol - 1;
-		mcol = mcols - 1;
-		while (!*p) {
+	    } while (!*p || (mcol != omcol && *p == op));
+	    wishcol = mcol;
+	} else if (cmd == Th(z_backwardchar) || cmd == Th(z_vibackwardchar)) {
+	    int omcol = mcol;
+	    Cmatch *op = *p;
+
+	    do {
+		if (!mcol) {
+		    mcol = mcols - 1;
+		    p += mcol;
+		} else {
 		    mcol--;
 		    p--;
 		}
-		wishcol = mcols - 1;
-	    } else if (cmd == Th(z_forwardword) ||
-		       cmd == Th(z_emacsforwardword) ||
-		       cmd == Th(z_viforwardword) ||
-		       cmd == Th(z_viforwardwordend)) {
-		Cmgroup g = *pg;
-		int ol = mline;
-
-		do {
-		    if (mline == mlines - 1) {
-			p -= mline * mcols;
-			pg -= mline * mcols;
-			mline = 0;
-		    } else {
-			mline++;
-			p += mcols;
-			pg += mcols;
-		    }
-		    if (adjust_mcol(wishcol, &p, &pg))
-			continue;
-		} while (ol != mline && (*pg == g || !*pg));
-	    } else if (cmd == Th(z_backwardword) ||
-		       cmd == Th(z_emacsbackwardword) ||
-		       cmd == Th(z_vibackwardword)) {
-		Cmgroup g = *pg;
-		int ol = mline;
-
-		do {
-		    if (!mline) {
-			mline = mlines - 1;
-			p += mline * mcols;
-			pg += mline * mcols;
-		    } else {
-			mline--;
-			p -= mcols;
-			pg -= mcols;
-		    }
-		    if (adjust_mcol(wishcol, &p, &pg))
-			continue;
-		} while (ol != mline && (*pg == g || !*pg));
-	    } else if (cmd == Th(z_completeword) ||
-		       cmd == Th(z_expandorcomplete) ||
-		       cmd == Th(z_expandorcompleteprefix) ||
-		       cmd == Th(z_menucomplete) ||
-		       cmd == Th(z_menuexpandorcomplete) ||
-		       !strcmp(cmd->nam, "menu-select") ||
-		       !strcmp(cmd->nam, "complete-word") ||
-		       !strcmp(cmd->nam, "expand-or-complete") ||
-		       !strcmp(cmd->nam, "expand-or-complete-prefix") ||
-		       !strcmp(cmd->nam, "menu-complete") ||
-		       !strcmp(cmd->nam, "menu-expand-or-complete")) {
-		do_menucmp(0);
-		mselect = (*(minfo.cur))->gnum;
-		setwish = 1;
-		continue;
-	    } else if (cmd == Th(z_reversemenucomplete) ||
-		       !strcmp(cmd->nam, "reverse-menu-complete")) {
-		reversemenucomplete(zlenoargs);
-		mselect = (*(minfo.cur))->gnum;
-		setwish = 1;
-		continue;
-	    } else {
-		ungetkeycmd();
-		break;
+	    } while (!*p || (mcol != omcol && *p == op));
+	    wishcol = mcol;
+	} else if (cmd == Th(z_beginningofbufferorhistory) ||
+		   cmd == Th(z_beginningofline) ||
+		   cmd == Th(z_beginningoflinehist) ||
+		   cmd == Th(z_vibeginningofline)) {
+	    p -= mcol;
+	    mcol = 0;
+	    while (!*p) {
+		mcol++;
+		p++;
 	    }
-	    do_single(**p);
-	    mselect = (**p)->gnum;
-	}
-	if (u)
-	    for (; u; u = u->prev)
-		if (u->lastmatches != lastmatches)
-		    freematches(u->lastmatches);
-
-	selectlocalmap(NULL);
-	mselect = -1;
-	inselect = 0;
-	if (acc) {
-	    menucmp = lastambig = hasoldlist = 0;
-	    do_single(*(minfo.cur));
-	}
-	if (wasnext) {
-	    menucmp = 2;
-	    showinglist = -2;
-	    minfo.asked = 0;
-	}
-	if (!noselect) {
-	    showinglist = -2;
-	    onlyexpl = oe;
-	    if (!smatches)
-		clearlist = 1;
-	    zrefresh();
+	    wishcol = 0;
+	} else if (cmd == Th(z_endofbufferorhistory) ||
+		   cmd == Th(z_endofline) ||
+		   cmd == Th(z_endoflinehist) ||
+		   cmd == Th(z_viendofline)) {
+	    p += mcols - mcol - 1;
+	    mcol = mcols - 1;
+	    while (!*p) {
+		mcol--;
+		p--;
+	    }
+	    wishcol = mcols - 1;
+	} else if (cmd == Th(z_forwardword) ||
+		   cmd == Th(z_emacsforwardword) ||
+		   cmd == Th(z_viforwardword) ||
+		   cmd == Th(z_viforwardwordend)) {
+	    Cmgroup g = *pg;
+	    int ol = mline;
+
+	    do {
+		if (mline == mlines - 1) {
+		    p -= mline * mcols;
+		    pg -= mline * mcols;
+		    mline = 0;
+		} else {
+		    mline++;
+		    p += mcols;
+		    pg += mcols;
+		}
+		if (adjust_mcol(wishcol, &p, &pg))
+		    continue;
+	    } while (ol != mline && (*pg == g || !*pg));
+	} else if (cmd == Th(z_backwardword) ||
+		   cmd == Th(z_emacsbackwardword) ||
+		   cmd == Th(z_vibackwardword)) {
+	    Cmgroup g = *pg;
+	    int ol = mline;
+
+	    do {
+		if (!mline) {
+		    mline = mlines - 1;
+		    p += mline * mcols;
+		    pg += mline * mcols;
+		} else {
+		    mline--;
+		    p -= mcols;
+		    pg -= mcols;
+		}
+		if (adjust_mcol(wishcol, &p, &pg))
+		    continue;
+	    } while (ol != mline && (*pg == g || !*pg));
+	} else if (cmd == Th(z_completeword) ||
+		   cmd == Th(z_expandorcomplete) ||
+		   cmd == Th(z_expandorcompleteprefix) ||
+		   cmd == Th(z_menucomplete) ||
+		   cmd == Th(z_menuexpandorcomplete) ||
+		   !strcmp(cmd->nam, "menu-select") ||
+		   !strcmp(cmd->nam, "complete-word") ||
+		   !strcmp(cmd->nam, "expand-or-complete") ||
+		   !strcmp(cmd->nam, "expand-or-complete-prefix") ||
+		   !strcmp(cmd->nam, "menu-complete") ||
+		   !strcmp(cmd->nam, "menu-expand-or-complete")) {
+	    do_menucmp(0);
+	    mselect = (*(minfo.cur))->gnum;
+	    setwish = 1;
+	    continue;
+	} else if (cmd == Th(z_reversemenucomplete) ||
+		   !strcmp(cmd->nam, "reverse-menu-complete")) {
+	    reversemenucomplete(zlenoargs);
+	    mselect = (*(minfo.cur))->gnum;
+	    setwish = 1;
+	    continue;
+	} else {
+	    ungetkeycmd();
+	    break;
 	}
-	fdat = NULL;
-    } LASTALLOC;
+	do_single(**p);
+	mselect = (**p)->gnum;
+    }
+    if (u)
+	for (; u; u = u->prev)
+	    if (u->lastmatches != lastmatches)
+		freematches(u->lastmatches);
+
+    selectlocalmap(NULL);
+    mselect = -1;
+    inselect = 0;
+    if (acc) {
+	menucmp = lastambig = hasoldlist = 0;
+	do_single(*(minfo.cur));
+    }
+    if (wasnext) {
+	menucmp = 2;
+	showinglist = -2;
+	minfo.asked = 0;
+    }
+    if (!noselect) {
+	showinglist = -2;
+	onlyexpl = oe;
+	if (!smatches)
+	    clearlist = 1;
+	zrefresh();
+    }
+    fdat = NULL;
+
     return (!noselect ^ acc);
 }
 
diff -ru ../z.old/Src/Zle/compresult.c Src/Zle/compresult.c
--- ../z.old/Src/Zle/compresult.c	Wed Feb 23 14:22:08 2000
+++ Src/Zle/compresult.c	Wed Feb 23 14:23:54 2000
@@ -924,44 +924,40 @@
 	return;
     }
     /* Otherwise go to the next match in the array... */
-    HEAPALLOC {
-	do {
-	    if (!*++(minfo.cur)) {
-		do {
-		    if (!(minfo.group = (minfo.group)->next))
-			minfo.group = amatches;
-		} while (!(minfo.group)->mcount);
-		minfo.cur = minfo.group->matches;
-	    }
-	} while (menuacc &&
-		 !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr));
-	/* ... and insert it into the command line. */
-	metafy_line();
-	do_single(*(minfo.cur));
-	unmetafy_line();
-    } LASTALLOC;
+    do {
+	if (!*++(minfo.cur)) {
+	    do {
+		if (!(minfo.group = (minfo.group)->next))
+		    minfo.group = amatches;
+	    } while (!(minfo.group)->mcount);
+	    minfo.cur = minfo.group->matches;
+	}
+    } while (menuacc &&
+	     !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr));
+    /* ... and insert it into the command line. */
+    metafy_line();
+    do_single(*(minfo.cur));
+    unmetafy_line();
 }
 
 /**/
 int
 reverse_menu(Hookdef dummy, void *dummy2)
 {
-    HEAPALLOC {
-	do {
-	    if (minfo.cur == (minfo.group)->matches) {
-		do {
-		    if (!(minfo.group = (minfo.group)->prev))
-			minfo.group = lmatches;
-		} while (!(minfo.group)->mcount);
-		minfo.cur = (minfo.group)->matches + (minfo.group)->mcount - 1;
-	    } else
-		minfo.cur--;
-	} while (menuacc &&
-		 !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr));
-	metafy_line();
-	do_single(*(minfo.cur));
-	unmetafy_line();
-    } LASTALLOC;
+    do {
+	if (minfo.cur == (minfo.group)->matches) {
+	    do {
+		if (!(minfo.group = (minfo.group)->prev))
+		    minfo.group = lmatches;
+	    } while (!(minfo.group)->mcount);
+	    minfo.cur = (minfo.group)->matches + (minfo.group)->mcount - 1;
+	} else
+	    minfo.cur--;
+    } while (menuacc &&
+	     !hasbrpsfx(*(minfo.cur), minfo.prebr, minfo.postbr));
+    metafy_line();
+    do_single(*(minfo.cur));
+    unmetafy_line();
 
     return 0;
 }
@@ -1100,9 +1096,7 @@
 {
     int alt;
 
-    PERMALLOC {
-	alt = permmatches(0);
-    } LASTALLOC;
+    alt = permmatches(0);
 
     if (normal)
 	return (alt ? 0 : nmatches);
@@ -1118,9 +1112,7 @@
 {
     Cmgroup oam;
 
-    PERMALLOC {
-	permmatches(0);
-    } LASTALLOC;
+    permmatches(0);
 
     oam = amatches;
     amatches = pmatches;
@@ -1829,20 +1821,18 @@
     struct chdata dat;
     int ret;
 
-    HEAPALLOC {
 #ifdef DEBUG
-	/* Sanity check */
-	if (!validlist) {
-	    showmsg("BUG: listmatches called with bogus list");
-	    return 1;
-	}
+    /* Sanity check */
+    if (!validlist) {
+	showmsg("BUG: listmatches called with bogus list");
+	return 1;
+    }
 #endif
 
-	dat.matches = amatches;
-	dat.num = nmatches;
-	dat.cur = NULL;
-	ret = runhookdef(COMPLISTMATCHESHOOK, (void *) &dat);
-    } LASTALLOC;
+    dat.matches = amatches;
+    dat.num = nmatches;
+    dat.cur = NULL;
+    ret = runhookdef(COMPLISTMATCHESHOOK, (void *) &dat);
 
     return ret;
 }
diff -ru ../z.old/Src/Zle/computil.c Src/Zle/computil.c
--- ../z.old/Src/Zle/computil.c	Wed Feb 23 14:22:08 2000
+++ Src/Zle/computil.c	Wed Feb 23 14:23:54 2000
@@ -130,9 +130,7 @@
 	    zerrnam(nam, "invalid argument: %s", *args, 0);
 	    return 1;
 	}
-	PERMALLOC {
-	    set->strs = arrdup(ap);
-	} LASTALLOC;
+	set->strs = zarrdup(ap);
 
 	if (disp)
 	    cdisp_calc(&(cd_state.disp), set->strs);
@@ -142,9 +140,7 @@
 		zerrnam(nam, "invalid argument: %s", *args, 0);
 		return 1;
 	    }
-	    PERMALLOC {
-		set->matches = arrdup(ap);
-	    } LASTALLOC;
+	    set->matches = zarrdup(ap);
 	    args++;
 	}
 	for (ap = args; *args &&
@@ -153,9 +149,7 @@
 
 	tmp = *args;
 	*args = NULL;
-	PERMALLOC {
-	    set->opts = arrdup(ap);
-	} LASTALLOC;
+	set->opts = zarrdup(ap);
 	if ((*args = tmp))
 	    args++;
     }
@@ -234,9 +228,7 @@
 	}
 	*sdp = *ssp = *mdp = *msp = NULL;
 
-	PERMALLOC {
-	    p = arrdup(set->opts);
-	} LASTALLOC;
+	p = zarrdup(set->opts);
 
 	setaparam(params[0], p);
 	setaparam(params[1], sd);
@@ -547,21 +539,19 @@
 
     /* Looks good. Optimistically allocate the cadef structure. */
 
-    PERMALLOC {
-	ret = (Cadef) zalloc(sizeof(*ret));
-	ret->next = NULL;
-	ret->opts = NULL;
-	ret->args = ret->rest = NULL;
-	ret->defs = arrdup(oargs);
-	ret->ndefs = arrlen(oargs);
-	ret->lastt = time(0);
-	if (single) {
-	    ret->single = (Caopt *) zalloc(256 * sizeof(Caopt));
-	    memset(ret->single, 0, 256 * sizeof(Caopt));
-	} else
-	    ret->single = NULL;
-	ret->match = ztrdup(match);
-    } LASTALLOC;
+    ret = (Cadef) zalloc(sizeof(*ret));
+    ret->next = NULL;
+    ret->opts = NULL;
+    ret->args = ret->rest = NULL;
+    ret->defs = zarrdup(oargs);
+    ret->ndefs = arrlen(oargs);
+    ret->lastt = time(0);
+    if (single) {
+	ret->single = (Caopt *) zalloc(256 * sizeof(Caopt));
+	memset(ret->single, 0, 256 * sizeof(Caopt));
+    } else
+	ret->single = NULL;
+    ret->match = ztrdup(match);
 
     /* Get the definitions. */
 
@@ -752,32 +742,30 @@
 	    }
 	    /* Store the option definition. */
 
-	    PERMALLOC {
-		*optp = opt = (Caopt) zalloc(sizeof(*opt));
-		optp = &((*optp)->next);
-
-		opt->next = NULL;
-		opt->name = ztrdup(rembslashcolon(name));
-		if (descr)
-		    opt->descr = ztrdup(descr);
-		else if (adpre && oargs && !oargs->next) {
-		    char *d;
-
-		    for (d = oargs->descr; *d; d++)
-			if (!iblank(*d))
-			    break;
+	    *optp = opt = (Caopt) zalloc(sizeof(*opt));
+	    optp = &((*optp)->next);
 
-		    if (*d)
-			opt->descr = tricat(adpre, oargs->descr, adsuf);
-		    else
-			opt->descr = NULL;
-		} else
+	    opt->next = NULL;
+	    opt->name = ztrdup(rembslashcolon(name));
+	    if (descr)
+		opt->descr = ztrdup(descr);
+	    else if (adpre && oargs && !oargs->next) {
+		char *d;
+
+		for (d = oargs->descr; *d; d++)
+		    if (!iblank(*d))
+			break;
+
+		if (*d)
+		    opt->descr = tricat(adpre, oargs->descr, adsuf);
+		else
 		    opt->descr = NULL;
-		opt->xor = xor;
-		opt->type = otype;
-		opt->args = oargs;
-		opt->num = nopts++;
-	    } LASTALLOC;
+	    } else
+		opt->descr = NULL;
+	    opt->xor = xor;
+	    opt->type = otype;
+	    opt->args = oargs;
+	    opt->num = nopts++;
 
 	    if (otype == CAO_DIRECT)
 		ndopts++;
@@ -1064,11 +1052,10 @@
 	state.nth = state.inopt = state.inarg = state.opt = state.arg = 1;
     state.inrest = state.doff = state.singles = state.doff = 0;
     state.curpos = compcurrent;
-    PERMALLOC {
-	state.args = newlinklist();
-	state.oargs = (LinkList *) zalloc(d->nopts * sizeof(LinkList));
-	memset(state.oargs, 0, d->nopts * sizeof(LinkList));
-    } LASTALLOC;
+    state.args = znewlinklist();
+    state.oargs = (LinkList *) zalloc(d->nopts * sizeof(LinkList));
+    memset(state.oargs, 0, d->nopts * sizeof(LinkList));
+
     ca_alloced = 1;
 
     memcpy(&ca_laststate, &state, sizeof(state));
@@ -1089,11 +1076,9 @@
 
 	if (state.def) {
 	    state.arg = 0;
-	    if (state.curopt) {
-		PERMALLOC {
-		    addlinknode(state.oargs[state.curopt->num], ztrdup(line));
-		} LASTALLOC;
-	    }
+	    if (state.curopt)
+		zaddlinknode(state.oargs[state.curopt->num], ztrdup(line));
+
 	    state.opt = (state.def->type == CAA_OPT);
 
 	    if (state.def->type == CAA_REST || state.def->type == CAA_RARGS ||
@@ -1133,9 +1118,8 @@
 	    state.singles = (d->single && (!pe || !*pe) &&
 			     state.curopt->name[1] && !state.curopt->name[2]);
 
-	    PERMALLOC {
-		state.oargs[state.curopt->num] = newlinklist();
-	    } LASTALLOC;
+	    state.oargs[state.curopt->num] = znewlinklist();
+
 	    ca_inactive(d, state.curopt->xor);
 
 	    /* Collect the argument strings. Maybe. */
@@ -1149,9 +1133,8 @@
 		    state.def->type != CAA_RARGS &&
 		    state.def->type != CAA_RREST)
 		    state.def = state.def->next;
-		PERMALLOC {
-		    addlinknode(state.oargs[state.curopt->num], ztrdup(pe));
-		} LASTALLOC;
+
+		zaddlinknode(state.oargs[state.curopt->num], ztrdup(pe));
 	    }
 	    if (state.def)
 		state.opt = 0;
@@ -1174,9 +1157,8 @@
 
 	    for (p = line + 1; p < pe; p++) {
 		if ((tmpopt = d->single[STOUC(*p)])) {
-		    PERMALLOC {
-			state.oargs[tmpopt->num] = newlinklist();
-		    } LASTALLOC;
+		    state.oargs[tmpopt->num] = znewlinklist();
+
 		    ca_inactive(d, tmpopt->xor);
 		}
 	    }
@@ -1189,9 +1171,8 @@
 		    state.def->type != CAA_RARGS &&
 		    state.def->type != CAA_RREST)
 		    state.def = state.def->next;
-		PERMALLOC {
-		    addlinknode(state.oargs[state.curopt->num], ztrdup(pe));
-		} LASTALLOC;
+
+		zaddlinknode(state.oargs[state.curopt->num], ztrdup(pe));
 	    }
 	    if (state.def)
 		state.opt = 0;
@@ -1211,19 +1192,16 @@
 		state.optbeg = state.nargbeg;
 		state.argbeg = cur - 1;
 
-		for (; line; line = compwords[cur++]) {
-		    PERMALLOC {
-			addlinknode(state.args, ztrdup(line));
-		    } LASTALLOC;
-		}
+		for (; line; line = compwords[cur++])
+		    zaddlinknode(state.args, ztrdup(line));
+
 		memcpy(&ca_laststate, &state, sizeof(state));
 		ca_laststate.ddef = NULL;
 		ca_laststate.doff = 0;
 		break;
 	    }
-	    PERMALLOC {
-		addlinknode(state.args, ztrdup(line));
-	    } LASTALLOC;
+	    zaddlinknode(state.args, ztrdup(line));
+
 	    if (state.def && state.def->type != CAA_NORMAL &&
 		state.def->type != CAA_OPT && state.inarg) {
 		state.restbeg = cur;
@@ -1245,10 +1223,10 @@
 
 		if (cur < compcurrent)
 		    memcpy(&ca_laststate, &state, sizeof(state));
-		PERMALLOC {
-		    for (; line; line = compwords[cur++])
-			addlinknode(l, ztrdup(line));
-		} LASTALLOC;
+
+		for (; line; line = compwords[cur++])
+		    zaddlinknode(l, ztrdup(line));
+
 		ca_laststate.ddef = NULL;
 		ca_laststate.doff = 0;
 		break;
@@ -1624,17 +1602,15 @@
     }
     descr = *args++;
 
-    PERMALLOC {
-	ret = (Cvdef) zalloc(sizeof(*ret));
-	ret->descr = ztrdup(descr);
-	ret->hassep = hassep;
-	ret->sep = sep;
-	ret->next = NULL;
-	ret->vals = NULL;
-	ret->defs = arrdup(oargs);
-	ret->ndefs = arrlen(oargs);
-	ret->lastt = time(0);
-    } LASTALLOC;
+    ret = (Cvdef) zalloc(sizeof(*ret));
+    ret->descr = ztrdup(descr);
+    ret->hassep = hassep;
+    ret->sep = sep;
+    ret->next = NULL;
+    ret->vals = NULL;
+    ret->defs = zarrdup(oargs);
+    ret->ndefs = arrlen(oargs);
+    ret->lastt = time(0);
 
     for (valp = &(ret->vals); *args; args++) {
 	p = dupstring(*args);
@@ -1740,17 +1716,15 @@
 	    vtype = CVV_NOARG;
 	    arg = NULL;
 	}
-	PERMALLOC {
-	    *valp = val = (Cvval) zalloc(sizeof(*val));
-	    valp = &((*valp)->next);
-
-	    val->next = NULL;
-	    val->name = ztrdup(name);
-	    val->descr = ztrdup(descr);
-	    val->xor = xor;
-	    val->type = vtype;
-	    val->arg = arg;
-	} LASTALLOC;
+	*valp = val = (Cvval) zalloc(sizeof(*val));
+	valp = &((*valp)->next);
+
+	val->next = NULL;
+	val->name = ztrdup(name);
+	val->descr = ztrdup(descr);
+	val->xor = xor;
+	val->type = vtype;
+	val->arg = arg;
     }
     return ret;
 }
@@ -1837,9 +1811,8 @@
     state.d = d;
     state.def = NULL;
     state.val = NULL;
-    PERMALLOC {
-	state.vals = (LinkList) newlinklist();
-    } LASTALLOC;
+    state.vals = (LinkList) znewlinklist();
+
     cv_alloced = 1;
 
     if (d->hassep) {
@@ -1856,10 +1829,8 @@
 		    eq = "";
 
 		if ((ptr = cv_get_val(d, str))) {
-		    PERMALLOC {
-			addlinknode(state.vals, ztrdup(str));
-			addlinknode(state.vals, ztrdup(eq));
-		    } LASTALLOC;
+		    zaddlinknode(state.vals, ztrdup(str));
+		    zaddlinknode(state.vals, ztrdup(eq));
 
 		    cv_inactive(d, ptr->xor);
 		}
@@ -1885,10 +1856,8 @@
 			eq = "";
 
 		    if ((ptr = cv_get_val(d, str))) {
-			PERMALLOC {
-			    addlinknode(state.vals, ztrdup(str));
-			    addlinknode(state.vals, ztrdup(eq));
-			} LASTALLOC;
+			zaddlinknode(state.vals, ztrdup(str));
+			zaddlinknode(state.vals, ztrdup(eq));
 
 			cv_inactive(d, ptr->xor);
 		    }
@@ -1907,10 +1876,8 @@
 	    for (str = compprefix; *str; str++) {
 		tmp[0] = *str;
 		if ((ptr = cv_get_val(d, tmp))) {
-		    PERMALLOC {
-			addlinknode(state.vals, ztrdup(tmp));
-			addlinknode(state.vals, ztrdup(""));
-		    } LASTALLOC;
+		    zaddlinknode(state.vals, ztrdup(tmp));
+		    zaddlinknode(state.vals, ztrdup(""));
 
 		    cv_inactive(d, ptr->xor);
 		}
@@ -1918,10 +1885,8 @@
 	    for (str = compsuffix; *str; str++) {
 		tmp[0] = *str;
 		if ((ptr = cv_get_val(d, tmp))) {
-		    PERMALLOC {
-			addlinknode(state.vals, ztrdup(tmp));
-			addlinknode(state.vals, ztrdup(""));
-		    } LASTALLOC;
+		    zaddlinknode(state.vals, ztrdup(tmp));
+		    zaddlinknode(state.vals, ztrdup(""));
 
 		    cv_inactive(d, ptr->xor);
 		}
@@ -2238,9 +2203,7 @@
 
     comptags[locallevel] = t = (Ctags) zalloc(sizeof(*t));
 
-    PERMALLOC {
-	t->all = arrdup(tags + 1);
-    } LASTALLOC;
+    t->all = zarrdup(tags + 1);
     t->context = ztrdup(*tags);
     t->sets = NULL;
     t->init = 1;
@@ -2332,10 +2295,7 @@
 	if (comptags[locallevel]->sets) {
 	    char **ret;
 
-	    PERMALLOC {
-		ret = arrdup(comptags[locallevel]->sets->tags);
-	    } LASTALLOC;
-
+	    ret = zarrdup(comptags[locallevel]->sets->tags);
 	    setaparam(args[1], ret);
 	} else
 	    return 1;
@@ -2377,9 +2337,7 @@
 	if (*args) {
 	    Ctset s = (Ctset) zalloc(sizeof(*s)), l;
 
-	    PERMALLOC {
-		s->tags = arrdup(args);
-	    } LASTALLOC;
+	    s->tags = zarrdup(args);
 	    s->next = NULL;
 
 	    if ((l = comptags[lasttaglevel]->sets)) {
diff -ru ../z.old/Src/Zle/zle_hist.c Src/Zle/zle_hist.c
--- ../z.old/Src/Zle/zle_hist.c	Wed Feb 23 14:22:09 2000
+++ Src/Zle/zle_hist.c	Wed Feb 23 14:23:55 2000
@@ -252,7 +252,7 @@
 
     if (!(he = movehistent(quietgethist(histline), 1, HIST_FOREIGN)))
 	return 1;
-    pushnode(bufstack, ztrdup(ZLETEXT(he)));
+    zpushnode(bufstack, ztrdup(ZLETEXT(he)));
     done = 1;
     stackhist = he->histnum;
     return 0;
@@ -506,9 +506,9 @@
 
     if (n < 0)
 	return 1;
-    pushnode(bufstack, metafy((char *) line, ll, META_DUP));
+    zpushnode(bufstack, metafy((char *) line, ll, META_DUP));
     while (--n)
-	pushnode(bufstack, ztrdup(""));
+	zpushnode(bufstack, ztrdup(""));
     stackcs = cs;
     *line = '\0';
     ll = cs = 0;
@@ -902,7 +902,7 @@
 	 he; he = movehistent(he, -1, HIST_FOREIGN)) {
 	if (!metadiffer(ZLETEXT(he), (char *) line, ll)) {
 	    he = movehistent(he, 1, HIST_FOREIGN);
-	    pushnode(bufstack, ztrdup(ZLETEXT(he)));
+	    zpushnode(bufstack, ztrdup(ZLETEXT(he)));
 	    stackhist = he->histnum;
 	    return 0;
 	}
diff -ru ../z.old/Src/Zle/zle_main.c Src/Zle/zle_main.c
--- ../z.old/Src/Zle/zle_main.c	Wed Feb 23 14:22:09 2000
+++ Src/Zle/zle_main.c	Wed Feb 23 14:23:55 2000
@@ -508,94 +508,94 @@
     pmpt_attr = txtchange;
     rpromptbuf = promptexpand(rp, 1, NULL, NULL);
     rpmpt_attr = txtchange;
-    PERMALLOC {
-	zlereadflags = flags;
-	histline = curhist;
+
+    zlereadflags = flags;
+    histline = curhist;
 #ifdef HAVE_SELECT
-	FD_ZERO(&foofd);
+    FD_ZERO(&foofd);
 #endif
-	undoing = 1;
-	line = (unsigned char *)zalloc((linesz = 256) + 2);
-	virangeflag = lastcmd = done = cs = ll = mark = 0;
-	vichgflag = 0;
-	viinsbegin = 0;
+    undoing = 1;
+    line = (unsigned char *)zalloc((linesz = 256) + 2);
+    virangeflag = lastcmd = done = cs = ll = mark = 0;
+    vichgflag = 0;
+    viinsbegin = 0;
+    statusline = NULL;
+    selectkeymap("main", 1);
+    selectlocalmap(NULL);
+    fixsuffix();
+    if ((s = (unsigned char *)getlinknode(bufstack))) {
+	setline((char *)s);
+	zsfree((char *)s);
+	if (stackcs != -1) {
+	    cs = stackcs;
+	    stackcs = -1;
+	    if (cs > ll)
+		cs = ll;
+	}
+	if (stackhist != -1) {
+	    histline = stackhist;
+	    stackhist = -1;
+	}
+    }
+    initundo();
+    if (isset(PROMPTCR))
+	putc('\r', shout);
+    if (tmout)
+	alarm(tmout);
+    zleactive = 1;
+    resetneeded = 1;
+    errflag = retflag = 0;
+    lastcol = -1;
+    initmodifier(&zmod);
+    prefixflag = 0;
+    zrefresh();
+    while (!done && !errflag) {
+
 	statusline = NULL;
-	selectkeymap("main", 1);
+	vilinerange = 0;
+	reselectkeymap();
 	selectlocalmap(NULL);
-	fixsuffix();
-	if ((s = (unsigned char *)getlinknode(bufstack))) {
-	    setline((char *)s);
-	    zsfree((char *)s);
-	    if (stackcs != -1) {
-		cs = stackcs;
-		stackcs = -1;
-		if (cs > ll)
-		    cs = ll;
-	    }
-	    if (stackhist != -1) {
-		histline = stackhist;
-		stackhist = -1;
-	    }
+	bindk = getkeycmd();
+	if (!ll && isfirstln && c == eofchar) {
+	    eofsent = 1;
+	    break;
+	}
+	if (bindk) {
+	    if (execzlefunc(bindk, zlenoargs))
+		handlefeep(zlenoargs);
+	    handleprefixes();
+	    /* for vi mode, make sure the cursor isn't somewhere illegal */
+	    if (invicmdmode() && cs > findbol() &&
+		(cs == ll || line[cs] == '\n'))
+		cs--;
+	    if (undoing)
+		handleundo();
+	} else {
+	    errflag = 1;
+	    break;
 	}
-	initundo();
-	if (isset(PROMPTCR))
-	    putc('\r', shout);
-	if (tmout)
-	    alarm(tmout);
-	zleactive = 1;
-	resetneeded = 1;
-	errflag = retflag = 0;
-	lastcol = -1;
-	initmodifier(&zmod);
-	prefixflag = 0;
-	zrefresh();
-	while (!done && !errflag) {
-
-	    statusline = NULL;
-	    vilinerange = 0;
-	    reselectkeymap();
-	    selectlocalmap(NULL);
-	    bindk = getkeycmd();
-	    if (!ll && isfirstln && c == eofchar) {
-		eofsent = 1;
-		break;
-	    }
-	    if (bindk) {
-		if (execzlefunc(bindk, zlenoargs))
-		    handlefeep(zlenoargs);
-		handleprefixes();
-		/* for vi mode, make sure the cursor isn't somewhere illegal */
-		if (invicmdmode() && cs > findbol() &&
-		    (cs == ll || line[cs] == '\n'))
-		    cs--;
-		if (undoing)
-		    handleundo();
-	    } else {
-		errflag = 1;
-		break;
-	    }
 #ifdef HAVE_SELECT
-	    if (baud && !(lastcmd & ZLE_MENUCMP)) {
-		FD_SET(SHTTY, &foofd);
-		tv.tv_sec = 0;
-		if ((tv.tv_usec = cost * costmult) > 500000)
-		    tv.tv_usec = 500000;
-		if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
-					NULL, NULL, &tv) <= 0)
-		    zrefresh();
-	    } else
+	if (baud && !(lastcmd & ZLE_MENUCMP)) {
+	    FD_SET(SHTTY, &foofd);
+	    tv.tv_sec = 0;
+	    if ((tv.tv_usec = cost * costmult) > 500000)
+		tv.tv_usec = 500000;
+	    if (!kungetct && select(SHTTY+1, (SELECT_ARG_2_T) & foofd,
+				    NULL, NULL, &tv) <= 0)
+		zrefresh();
+	} else
 #endif
-		if (!kungetct)
-		    zrefresh();
-	}
-	statusline = NULL;
-	invalidatelist();
-	trashzle();
-	free(lpromptbuf);
-	free(rpromptbuf);
-	zleactive = zlereadflags = 0;
-	alarm(0);
-    } LASTALLOC;
+	    if (!kungetct)
+		zrefresh();
+    }
+    statusline = NULL;
+    invalidatelist();
+    trashzle();
+    free(lpromptbuf);
+    free(rpromptbuf);
+    zleactive = zlereadflags = 0;
+    alarm(0);
+
     freeundo();
     if (eofsent) {
 	free(line);
@@ -835,9 +835,8 @@
 	haso = 1;
     }
     /* edit the parameter value */
-    PERMALLOC {
-	pushnode(bufstack, ztrdup(s));
-    } LASTALLOC;
+    zpushnode(bufstack, ztrdup(s));
+
     varedarg = *args;
     ifl = isfirstln;
     if (ops['e'])
@@ -876,9 +875,7 @@
     if (pm && (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED))) {
 	char **a;
 
-	PERMALLOC {
-	    a = spacesplit(t, 1);
-	} LASTALLOC;
+	a = spacesplit(t, 1, 0);
 	if (PM_TYPE(pm->flags) == PM_ARRAY)
 	    setaparam(args[0], a);
 	else
diff -ru ../z.old/Src/Zle/zle_misc.c Src/Zle/zle_misc.c
--- ../z.old/Src/Zle/zle_misc.c	Wed Feb 23 14:22:09 2000
+++ Src/Zle/zle_misc.c	Wed Feb 23 14:23:55 2000
@@ -274,7 +274,7 @@
 int
 acceptandhold(char **args)
 {
-    pushnode(bufstack, metafy((char *)line, ll, META_DUP));
+    zpushnode(bufstack, metafy((char *)line, ll, META_DUP));
     stackcs = cs;
     done = 1;
     return 0;
@@ -745,12 +745,11 @@
 		cmd == Th(z_acceptline) || c == ' ' || c == '\t') {
 		cmdambig = 100;
 
-		HEAPALLOC {
-		    cmdll = newlinklist();
-		    *ptr = 0;
+		cmdll = newlinklist();
+		*ptr = 0;
+
+		scanhashtable(thingytab, 1, 0, DISABLED, scancompcmd, 0);
 
-		    scanhashtable(thingytab, 1, 0, DISABLED, scancompcmd, 0);
-		} LASTALLOC;
 		if (empty(cmdll)) {
 		    feep = 1;
 		    if (listed)
diff -ru ../z.old/Src/Zle/zle_thingy.c Src/Zle/zle_thingy.c
--- ../z.old/Src/Zle/zle_thingy.c	Wed Feb 23 14:22:10 2000
+++ Src/Zle/zle_thingy.c	Wed Feb 23 14:23:55 2000
@@ -637,9 +637,7 @@
     }
 
     t = rthingy(wname);
-    PERMALLOC {
-        ret = execzlefunc(t, args);
-    } LASTALLOC;
+    ret = execzlefunc(t, args);
     unrefthingy(t);
     if (saveflag)
 	zmod = modsave;
diff -ru ../z.old/Src/Zle/zle_tricky.c Src/Zle/zle_tricky.c
--- ../z.old/Src/Zle/zle_tricky.c	Wed Feb 23 14:22:10 2000
+++ Src/Zle/zle_tricky.c	Wed Feb 23 14:23:56 2000
@@ -696,13 +696,13 @@
 		    *q = Nularg;
 	    cs = wb;
 	    foredel(we - wb);
-	    HEAPALLOC {
-		untokenize(x = ox = dupstring(w));
-		if (*w == Tilde || *w == Equals || *w == String)
-		    *x = *w;
-		spckword(&x, 0, lincmd, 0);
-		ret = !strcmp(x, ox);
-	    } LASTALLOC;
+
+	    untokenize(x = ox = dupstring(w));
+	    if (*w == Tilde || *w == Equals || *w == String)
+		*x = *w;
+	    spckword(&x, 0, lincmd, 0);
+	    ret = !strcmp(x, ox);
+
 	    untokenize(x);
 	    inststr(x);
 	} else if (COMP_ISEXPAND(lst)) {
@@ -810,7 +810,7 @@
 dupstrspace(const char *str)
 {
     int len = strlen((char *)str);
-    char *t = (char *) ncalloc(len + 2);
+    char *t = (char *) hcalloc(len + 2);
     strcpy(t, str);
     strcpy(t+len, " ");
     return t;
@@ -868,16 +868,17 @@
 
 /**/
 mod_export Brinfo
-dupbrinfo(Brinfo p, Brinfo *last)
+dupbrinfo(Brinfo p, Brinfo *last, int heap)
 {
     Brinfo ret = NULL, *q = &ret, n = NULL;
 
     while (p) {
-	n = *q = (Brinfo) alloc(sizeof(*n));
+	n = *q = (heap ? (Brinfo) zhalloc(sizeof(*n)) :
+		  (Brinfo) zalloc(sizeof(*n)));
 	q = &(n->next);
 
 	n->next = NULL;
-	n->str = dupstring(p->str);
+	n->str = (heap ? dupstring(p->str) : ztrdup(p->str));
 	n->pos = p->pos;
 	n->qpos = p->qpos;
 	n->curpos = p->curpos;
@@ -946,628 +947,618 @@
     addx(&tmp);
     linptr = (char *)line;
     pushheap();
-    HEAPALLOC {
-      start:
-	inwhat = IN_NOTHING;
-	/* Now set up the lexer and start it. */
-	parbegin = parend = -1;
-	lincmd = incmdpos;
-	linredir = inredir;
-	zsfree(cmdstr);
-	cmdstr = NULL;
-	zsfree(varname);
-	varname = NULL;
-	insubscr = 0;
-	zleparse = 1;
-	clwpos = -1;
-	lexsave();
-	inpush(dupstrspace((char *) linptr), 0, NULL);
-	strinbeg(0);
-	i = tt0 = cp = rd = ins = oins = linarr = parct = ia = 0;
-
-	/* This loop is possibly the wrong way to do this.  It goes through *
-	 * the previously massaged command line using the lexer.  It stores *
-	 * each token in each command (commands being regarded, roughly, as *
-	 * being separated by tokens | & &! |& || &&).  The loop stops when *
-	 * the end of the command containing the cursor is reached.  It's a *
-	 * simple way to do things, but suffers from an inability to        *
-	 * distinguish actual command arguments from, for example,          *
-	 * filenames in redirections.  (But note that code elsewhere checks *
-	 * if we are completing *in* a redirection.)  The only way to fix   *
-	 * this would be to pass the command line through the parser too,   *
-	 * and get the arguments that way.  Maybe in 3.1...                 */
-	do {
-	    lincmd = ((incmdpos && !ins) || (oins == 2 && i == 2) ||
-		      (ins == 3 && i == 1));
-	    linredir = (inredir && !ins);
-	    oins = ins;
-	    /* Get the next token. */
-	    if (linarr)
-		incmdpos = 0;
-	    ctxtlex();
 
-	    if (tok == LEXERR) {
-		if (!tokstr)
-		    break;
-		for (j = 0, p = tokstr; *p; p++)
-		    if (*p == Snull || *p == Dnull)
-			j++;
-		if (j & 1) {
-		    if (lincmd && strchr(tokstr, '=')) {
-			varq = 1;
-			tok = ENVSTRING;
-		    } else
-			tok = STRING;
-		}
-	    } else if (tok == ENVSTRING)
-		varq = 0;
-	    if (tok == ENVARRAY) {
-		linarr = 1;
-		zsfree(varname);
-		varname = ztrdup(tokstr);
-	    } else if (tok == INPAR)
-		parct++;
-	    else if (tok == OUTPAR) {
-		if (parct)
-		    parct--;
-		else
-		    linarr = 0;
-	    }
-	    if (inredir)
-		rdstr = tokstrings[tok];
-	    if (tok == DINPAR)
-		tokstr = NULL;
+ start:
+    inwhat = IN_NOTHING;
+    /* Now set up the lexer and start it. */
+    parbegin = parend = -1;
+    lincmd = incmdpos;
+    linredir = inredir;
+    zsfree(cmdstr);
+    cmdstr = NULL;
+    zsfree(varname);
+    varname = NULL;
+    insubscr = 0;
+    zleparse = 1;
+    clwpos = -1;
+    lexsave();
+    inpush(dupstrspace((char *) linptr), 0, NULL);
+    strinbeg(0);
+    i = tt0 = cp = rd = ins = oins = linarr = parct = ia = 0;
+
+    /* This loop is possibly the wrong way to do this.  It goes through *
+     * the previously massaged command line using the lexer.  It stores *
+     * each token in each command (commands being regarded, roughly, as *
+     * being separated by tokens | & &! |& || &&).  The loop stops when *
+     * the end of the command containing the cursor is reached.  It's a *
+     * simple way to do things, but suffers from an inability to        *
+     * distinguish actual command arguments from, for example,          *
+     * filenames in redirections.  (But note that code elsewhere checks *
+     * if we are completing *in* a redirection.)  The only way to fix   *
+     * this would be to pass the command line through the parser too,   *
+     * and get the arguments that way.  Maybe in 3.1...                 */
+    do {
+	lincmd = ((incmdpos && !ins) || (oins == 2 && i == 2) ||
+		  (ins == 3 && i == 1));
+	linredir = (inredir && !ins);
+	oins = ins;
+	/* Get the next token. */
+	if (linarr)
+	    incmdpos = 0;
+	ctxtlex();
 
-	    /* We reached the end. */
-	    if (tok == ENDINPUT)
-		break;
-	    if ((ins && (tok == DO || tok == SEPER)) ||
-		(ins == 2 && i == 2) ||	(ins == 3 && i == 3) ||
-		tok == BAR    || tok == AMPER     ||
-		tok == BARAMP || tok == AMPERBANG ||
-		((tok == DBAR || tok == DAMPER) && !incond)) {
-		/* This is one of the things that separate commands.  If we  *
-		 * already have the things we need (e.g. the token strings), *
-		 * leave the loop.                                           */
-		if (tt)
-		    break;
-		/* Otherwise reset the variables we are collecting data in. */
-		i = tt0 = cp = rd = ins = 0;
-	    }
-	    if (lincmd && (tok == STRING || tok == FOR || tok == FOREACH ||
-			   tok == SELECT || tok == REPEAT || tok == CASE)) {
-		/* The lexer says, this token is in command position, so *
-		 * store the token string (to find the right compctl).   */
-		ins = (tok == REPEAT ? 2 : (tok != STRING));
-		zsfree(cmdstr);
-		cmdstr = ztrdup(tokstr);
-		i = 0;
-	    }
-	    if (!zleparse && !tt0) {
-		/* This is done when the lexer reached the word the cursor is on. */
-		tt = tokstr ? dupstring(tokstr) : NULL;
-		/* If we added a `x', remove it. */
-		if (addedx && tt)
-		    chuck(tt + cs - wb);
-		tt0 = tok;
-		/* Store the number of this word. */
-		clwpos = i;
-		cp = lincmd;
-		rd = linredir;
-		ia = linarr;
-		if (inwhat == IN_NOTHING && incond)
-		    inwhat = IN_COND;
-	    } else if (linredir)
-		continue;
+	if (tok == LEXERR) {
 	    if (!tokstr)
-		continue;
-	    /* Hack to allow completion after `repeat n do'. */
-	    if (oins == 2 && !i && !strcmp(tokstr, "do"))
-		ins = 3;
-	    /* We need to store the token strings of all words (for some of *
-	     * the more complicated compctl -x things).  They are stored in *
-	     * the clwords array.  Make this array big enough.              */
-	    if (i + 1 == clwsize) {
-		int n;
-		clwords = (char **)realloc(clwords,
-					   (clwsize *= 2) * sizeof(char *));
-		for(n = clwsize; --n > i; )
-		    clwords[n] = NULL;
+		break;
+	    for (j = 0, p = tokstr; *p; p++)
+		if (*p == Snull || *p == Dnull)
+		    j++;
+	    if (j & 1) {
+		if (lincmd && strchr(tokstr, '=')) {
+		    varq = 1;
+		    tok = ENVSTRING;
+		} else
+		    tok = STRING;
 	    }
-	    zsfree(clwords[i]);
-	    /* And store the current token string. */
-	    clwords[i] = ztrdup(tokstr);
-	    sl = strlen(tokstr);
-	    /* Sometimes the lexer gives us token strings ending with *
-	     * spaces we delete the spaces.                           */
-	    while (sl && clwords[i][sl - 1] == ' ' &&
-		   (sl < 2 || (clwords[i][sl - 2] != Bnull &&
-			       clwords[i][sl - 2] != Meta)))
-		clwords[i][--sl] = '\0';
-	    /* If this is the word the cursor is in and we added a `x', *
-	     * remove it.                                               */
-	    if (clwpos == i++ && addedx)
-		chuck(&clwords[i - 1][((cs - wb) >= sl) ?
-				     (sl - 1) : (cs - wb)]);
-	} while (tok != LEXERR && tok != ENDINPUT &&
-		 (tok != SEPER || (zleparse && !tt0)));
-	/* Calculate the number of words stored in the clwords array. */
-	clwnum = (tt || !i) ? i : i - 1;
-	zsfree(clwords[clwnum]);
-	clwords[clwnum] = NULL;
-	t0 = tt0;
-	if (ia) {
-	    lincmd = linredir = 0;
-	    inwhat = IN_ENV;
-	} else {
-	    lincmd = cp;
-	    linredir = rd;
+	} else if (tok == ENVSTRING)
+	    varq = 0;
+	if (tok == ENVARRAY) {
+	    linarr = 1;
+	    zsfree(varname);
+	    varname = ztrdup(tokstr);
+	} else if (tok == INPAR)
+	    parct++;
+	else if (tok == OUTPAR) {
+	    if (parct)
+		parct--;
+	    else
+		linarr = 0;
+	}
+	if (inredir)
+	    rdstr = tokstrings[tok];
+	if (tok == DINPAR)
+	    tokstr = NULL;
+
+	/* We reached the end. */
+	if (tok == ENDINPUT)
+	    break;
+	if ((ins && (tok == DO || tok == SEPER)) ||
+	    (ins == 2 && i == 2) ||	(ins == 3 && i == 3) ||
+	    tok == BAR    || tok == AMPER     ||
+	    tok == BARAMP || tok == AMPERBANG ||
+	    ((tok == DBAR || tok == DAMPER) && !incond)) {
+	    /* This is one of the things that separate commands.  If we  *
+	     * already have the things we need (e.g. the token strings), *
+	     * leave the loop.                                           */
+	    if (tt)
+		break;
+	    /* Otherwise reset the variables we are collecting data in. */
+	    i = tt0 = cp = rd = ins = 0;
 	}
-	strinend();
-	inpop();
-	errflag = zleparse = 0;
-	if (parbegin != -1) {
-	    /* We are in command or process substitution if we are not in
-	     * a $((...)). */
-	    if (parend >= 0 && !tmp)
-		line = (unsigned char *) dupstring(tmp = (char *)line);
-	    linptr = (char *) line + ll + addedx - parbegin + 1;
-	    if ((linptr - (char *) line) < 3 || *linptr != '(' ||
-		linptr[-1] != '(' || linptr[-2] != '$') {
-		if (parend >= 0) {
-		    ll -= parend;
-		    line[ll + addedx] = '\0';
-		}
-		lexrestore();
-		goto start;
+	if (lincmd && (tok == STRING || tok == FOR || tok == FOREACH ||
+		       tok == SELECT || tok == REPEAT || tok == CASE)) {
+	    /* The lexer says, this token is in command position, so *
+	     * store the token string (to find the right compctl).   */
+	    ins = (tok == REPEAT ? 2 : (tok != STRING));
+	    zsfree(cmdstr);
+	    cmdstr = ztrdup(tokstr);
+	    i = 0;
+	}
+	if (!zleparse && !tt0) {
+	    /* This is done when the lexer reached the word the cursor is on. */
+	    tt = tokstr ? dupstring(tokstr) : NULL;
+	    /* If we added a `x', remove it. */
+	    if (addedx && tt)
+		chuck(tt + cs - wb);
+	    tt0 = tok;
+	    /* Store the number of this word. */
+	    clwpos = i;
+	    cp = lincmd;
+	    rd = linredir;
+	    ia = linarr;
+	    if (inwhat == IN_NOTHING && incond)
+		inwhat = IN_COND;
+	} else if (linredir)
+	    continue;
+	if (!tokstr)
+	    continue;
+	/* Hack to allow completion after `repeat n do'. */
+	if (oins == 2 && !i && !strcmp(tokstr, "do"))
+	    ins = 3;
+	/* We need to store the token strings of all words (for some of *
+	 * the more complicated compctl -x things).  They are stored in *
+	 * the clwords array.  Make this array big enough.              */
+	if (i + 1 == clwsize) {
+	    int n;
+	    clwords = (char **)realloc(clwords,
+				       (clwsize *= 2) * sizeof(char *));
+	    for(n = clwsize; --n > i; )
+		clwords[n] = NULL;
+	}
+	zsfree(clwords[i]);
+	/* And store the current token string. */
+	clwords[i] = ztrdup(tokstr);
+	sl = strlen(tokstr);
+	/* Sometimes the lexer gives us token strings ending with *
+	 * spaces we delete the spaces.                           */
+	while (sl && clwords[i][sl - 1] == ' ' &&
+	       (sl < 2 || (clwords[i][sl - 2] != Bnull &&
+			   clwords[i][sl - 2] != Meta)))
+	    clwords[i][--sl] = '\0';
+	/* If this is the word the cursor is in and we added a `x', *
+	 * remove it.                                               */
+	if (clwpos == i++ && addedx)
+	    chuck(&clwords[i - 1][((cs - wb) >= sl) ?
+				 (sl - 1) : (cs - wb)]);
+    } while (tok != LEXERR && tok != ENDINPUT &&
+	     (tok != SEPER || (zleparse && !tt0)));
+    /* Calculate the number of words stored in the clwords array. */
+    clwnum = (tt || !i) ? i : i - 1;
+    zsfree(clwords[clwnum]);
+    clwords[clwnum] = NULL;
+    t0 = tt0;
+    if (ia) {
+	lincmd = linredir = 0;
+	inwhat = IN_ENV;
+    } else {
+	lincmd = cp;
+	linredir = rd;
+    }
+    strinend();
+    inpop();
+    errflag = zleparse = 0;
+    if (parbegin != -1) {
+	/* We are in command or process substitution if we are not in
+	 * a $((...)). */
+	if (parend >= 0 && !tmp)
+	    line = (unsigned char *) dupstring(tmp = (char *)line);
+	linptr = (char *) line + ll + addedx - parbegin + 1;
+	if ((linptr - (char *) line) < 3 || *linptr != '(' ||
+	    linptr[-1] != '(' || linptr[-2] != '$') {
+	    if (parend >= 0) {
+		ll -= parend;
+		line[ll + addedx] = '\0';
 	    }
+	    lexrestore();
+	    goto start;
 	}
+    }
 
-	if (inwhat == IN_MATH)
+    if (inwhat == IN_MATH)
+	s = NULL;
+    else if (!t0 || t0 == ENDINPUT) {
+	/* There was no word (empty line). */
+	s = ztrdup("");
+	we = wb = cs;
+	clwpos = clwnum;
+	t0 = STRING;
+    } else if (t0 == STRING) {
+	/* We found a simple string. */
+	s = ztrdup(clwords[clwpos]);
+    } else if (t0 == ENVSTRING) {
+	char sav;
+	/* The cursor was inside a parameter assignment. */
+
+	if (varq)
+	    tt = clwords[clwpos];
+
+	for (s = tt; iident(*s); s++);
+	sav = *s;
+	*s = '\0';
+	zsfree(varname);
+	varname = ztrdup(tt);
+	*s = sav;
+	if (skipparens(Inbrack, Outbrack, &s) > 0 || s > tt + cs - wb) {
 	    s = NULL;
-	else if (!t0 || t0 == ENDINPUT) {
-	    /* There was no word (empty line). */
-	    s = ztrdup("");
-	    we = wb = cs;
-	    clwpos = clwnum;
+	    inwhat = IN_MATH;
+	    if ((keypm = (Param) paramtab->getnode(paramtab, varname)) &&
+		(keypm->flags & PM_HASHED))
+		insubscr = 2;
+	    else
+		insubscr = 1;
+	} else if (*s == '=' && cs > wb + (s - tt)) {
+	    s++;
+	    wb += s - tt;
 	    t0 = STRING;
-	} else if (t0 == STRING) {
-	    /* We found a simple string. */
-	    s = ztrdup(clwords[clwpos]);
-	} else if (t0 == ENVSTRING) {
-	    char sav;
-	    /* The cursor was inside a parameter assignment. */
-
-	    if (varq)
-		tt = clwords[clwpos];
-
-	    for (s = tt; iident(*s); s++);
-	    sav = *s;
-	    *s = '\0';
-	    zsfree(varname);
-	    varname = ztrdup(tt);
-	    *s = sav;
-	    if (skipparens(Inbrack, Outbrack, &s) > 0 || s > tt + cs - wb) {
-		s = NULL;
-		inwhat = IN_MATH;
-		if ((keypm = (Param) paramtab->getnode(paramtab, varname)) &&
-		    (keypm->flags & PM_HASHED))
-		    insubscr = 2;
-		else
-		    insubscr = 1;
-	    } else if (*s == '=' && cs > wb + (s - tt)) {
-		s++;
-		wb += s - tt;
-		t0 = STRING;
-		s = ztrdup(s);
-		inwhat = IN_ENV;
-	    }
-	    lincmd = 1;
+	    s = ztrdup(s);
+	    inwhat = IN_ENV;
 	}
-	if (we > ll)
-	    we = ll;
-	tt = (char *)line;
+	lincmd = 1;
+    }
+    if (we > ll)
+	we = ll;
+    tt = (char *)line;
+    if (tmp) {
+	line = (unsigned char *)tmp;
+	ll = strlen((char *)line);
+    }
+    if (t0 != STRING && inwhat != IN_MATH) {
 	if (tmp) {
-	    line = (unsigned char *)tmp;
-	    ll = strlen((char *)line);
-	}
-	if (t0 != STRING && inwhat != IN_MATH) {
-	    if (tmp) {
-		tmp = NULL;
-		linptr = (char *)line;
-		lexrestore();
-		addedx = 0;
-		goto start;
-	    }
-	    noaliases = 0;
+	    tmp = NULL;
+	    linptr = (char *)line;
 	    lexrestore();
-	    LASTALLOC_RETURN NULL;
+	    addedx = 0;
+	    goto start;
 	}
-
 	noaliases = 0;
+	lexrestore();
+	return NULL;
+    }
 
-	/* Check if we are in an array subscript.  We simply assume that  *
-	 * we are in a subscript if we are in brackets.  Correct solution *
-	 * is very difficult.  This is quite close, but gets things like  *
-	 * foo[_ wrong (note no $).  If we are in a subscript, treat it   *
-	 * as being in math.                                              */
-	if (inwhat != IN_MATH) {
-	    int i = 0;
-	    char *nnb = (iident(*s) ? s : s + 1), *nb = NULL, *ne = NULL;
-
-	    for (tt = s; ++tt < s + cs - wb;)
-		if (*tt == Inbrack) {
-		    i++;
-		    nb = nnb;
-		    ne = tt;
-		} else if (i && *tt == Outbrack)
-		    i--;
-		else if (!iident(*tt))
-		    nnb = tt + 1;
-	    if (i) {
-		inwhat = IN_MATH;
-		insubscr = 1;
-		if (nb < ne) {
-		    char sav = *ne;
-		    *ne = '\0';
-		    zsfree(varname);
-		    varname = ztrdup(nb);
-		    *ne = sav;
-		    if ((keypm = (Param) paramtab->getnode(paramtab,
-							   varname)) &&
-			(keypm->flags & PM_HASHED))
-			insubscr = 2;
-		}
+    noaliases = 0;
+
+    /* Check if we are in an array subscript.  We simply assume that  *
+     * we are in a subscript if we are in brackets.  Correct solution *
+     * is very difficult.  This is quite close, but gets things like  *
+     * foo[_ wrong (note no $).  If we are in a subscript, treat it   *
+     * as being in math.                                              */
+    if (inwhat != IN_MATH) {
+	int i = 0;
+	char *nnb = (iident(*s) ? s : s + 1), *nb = NULL, *ne = NULL;
+	
+	for (tt = s; ++tt < s + cs - wb;)
+	    if (*tt == Inbrack) {
+		i++;
+		nb = nnb;
+		ne = tt;
+	    } else if (i && *tt == Outbrack)
+		i--;
+	    else if (!iident(*tt))
+		nnb = tt + 1;
+	if (i) {
+	    inwhat = IN_MATH;
+	    insubscr = 1;
+	    if (nb < ne) {
+		char sav = *ne;
+		*ne = '\0';
+		zsfree(varname);
+		varname = ztrdup(nb);
+		*ne = sav;
+		if ((keypm = (Param) paramtab->getnode(paramtab, varname)) &&
+		    (keypm->flags & PM_HASHED))
+		    insubscr = 2;
 	    }
 	}
-	if (inwhat == IN_MATH) {
-	    if (compfunc || insubscr == 2) {
-		int lev;
-		char *p;
-
-		for (wb = cs - 1, lev = 0; wb > 0; wb--)
-		    if (line[wb] == ']' || line[wb] == ')')
-			lev++;
-		    else if (line[wb] == '[') {
-			if (!lev--)
-			    break;
-		    } else if (line[wb] == '(') {
-			if (!lev && line[wb - 1] == '(')
-			    break;
-			if (lev)
-			    lev--;
-		    }
-		p = (char *) line + wb;
-		wb++;
-		if (wb && (*p == '[' || *p == '(') &&
-		    !skipparens(*p, (*p == '[' ? ']' : ')'), &p)) {
-			we = (p - (char *) line) - 1;
-			if (insubscr == 2)
-			    insubscr = 3;
+    }
+    if (inwhat == IN_MATH) {
+	if (compfunc || insubscr == 2) {
+	    int lev;
+	    char *p;
+
+	    for (wb = cs - 1, lev = 0; wb > 0; wb--)
+		if (line[wb] == ']' || line[wb] == ')')
+		    lev++;
+		else if (line[wb] == '[') {
+		    if (!lev--)
+			break;
+		} else if (line[wb] == '(') {
+		    if (!lev && line[wb - 1] == '(')
+			break;
+		    if (lev)
+			lev--;
 		}
-	    } else {
-		/* In mathematical expression, we complete parameter names  *
-		 * (even if they don't have a `$' in front of them).  So we *
-		 * have to find that name.                                  */
-		for (we = cs; iident(line[we]); we++);
-		for (wb = cs; --wb >= 0 && iident(line[wb]););
-		wb++;
+	    p = (char *) line + wb;
+	    wb++;
+	    if (wb && (*p == '[' || *p == '(') &&
+		!skipparens(*p, (*p == '[' ? ']' : ')'), &p)) {
+		we = (p - (char *) line) - 1;
+		if (insubscr == 2)
+		    insubscr = 3;
 	    }
-	    zsfree(s);
-	    s = zalloc(we - wb + 1);
-	    strncpy(s, (char *) line + wb, we - wb);
-	    s[we - wb] = '\0';
-	    if (wb > 2 && line[wb - 1] == '[' && iident(line[wb - 2])) {
-		int i = wb - 3;
-		unsigned char sav = line[wb - 1];
+	} else {
+	    /* In mathematical expression, we complete parameter names  *
+	     * (even if they don't have a `$' in front of them).  So we *
+	     * have to find that name.                                  */
+	    for (we = cs; iident(line[we]); we++);
+	    for (wb = cs; --wb >= 0 && iident(line[wb]););
+	    wb++;
+	}
+	zsfree(s);
+	s = zalloc(we - wb + 1);
+	strncpy(s, (char *) line + wb, we - wb);
+	s[we - wb] = '\0';
+	if (wb > 2 && line[wb - 1] == '[' && iident(line[wb - 2])) {
+	    int i = wb - 3;
+	    unsigned char sav = line[wb - 1];
 
-		while (i >= 0 && iident(line[i]))
-		    i--;
+	    while (i >= 0 && iident(line[i]))
+		i--;
 
-		line[wb - 1] = '\0';
-		zsfree(varname);
-		varname = ztrdup((char *) line + i + 1);
-		line[wb - 1] = sav;
-		if ((keypm = (Param) paramtab->getnode(paramtab, varname)) &&
-		    (keypm->flags & PM_HASHED)) {
-		    if (insubscr != 3)
-			insubscr = 2;
-		} else
-		    insubscr = 1;
-	    }
+	    line[wb - 1] = '\0';
+	    zsfree(varname);
+	    varname = ztrdup((char *) line + i + 1);
+	    line[wb - 1] = sav;
+	    if ((keypm = (Param) paramtab->getnode(paramtab, varname)) &&
+		(keypm->flags & PM_HASHED)) {
+		if (insubscr != 3)
+		    insubscr = 2;
+	    } else
+		insubscr = 1;
 	}
-	/* This variable will hold the current word in quoted form. */
-	qword = ztrdup(s);
-	offs = cs - wb;
-	if ((p = parambeg(s))) {
-	    for (p = s; *p; p++)
-		if (*p == Dnull)
-		    *p = '"';
-		else if (*p == Snull)
-		    *p = '\'';
-	}
-	if ((*s == Snull || *s == Dnull) && !has_real_token(s + 1)) {
-	    char *q = (*s == Snull ? "'" : "\""), *n = tricat(qipre, q, "");
-	    int sl = strlen(s);
-
-	    instring = (*s == Snull ? 1 : 2);
-	    zsfree(qipre);
-	    qipre = n;
-	    if (sl > 1 && s[sl - 1] == *s) {
-		n = tricat(q, qisuf, "");
-		zsfree(qisuf);
-		qisuf = n;
-	    }
-	    autoq = ztrdup(q);
+    }
+    /* This variable will hold the current word in quoted form. */
+    qword = ztrdup(s);
+    offs = cs - wb;
+    if ((p = parambeg(s))) {
+	for (p = s; *p; p++)
+	    if (*p == Dnull)
+		*p = '"';
+	    else if (*p == Snull)
+		*p = '\'';
+    }
+    if ((*s == Snull || *s == Dnull) && !has_real_token(s + 1)) {
+	char *q = (*s == Snull ? "'" : "\""), *n = tricat(qipre, q, "");
+	int sl = strlen(s);
+
+	instring = (*s == Snull ? 1 : 2);
+	zsfree(qipre);
+	qipre = n;
+	if (sl > 1 && s[sl - 1] == *s) {
+	    n = tricat(q, qisuf, "");
+	    zsfree(qisuf);
+	    qisuf = n;
 	}
-	/* While building the quoted form, we also clean up the command line. */
-	for (p = s, tt = qword, i = wb; *p; p++, tt++, i++)
-	    if (INULL(*p)) {
-		if (i < cs)
-		    offs--;
-		if (p[1] || *p != Bnull) {
-		    if (*p == Bnull) {
-			*tt = '\\';
-			if (cs == i + 1)
-			    cs++, offs++;
-		    } else {
-			ocs = cs;
-			cs = i;
-			foredel(1);
-			chuck(tt--);
-			if ((cs = ocs) > i--)
-			    cs--;
-			we--;
-		    }
+	autoq = ztrdup(q);
+    }
+    /* While building the quoted form, we also clean up the command line. */
+    for (p = s, tt = qword, i = wb; *p; p++, tt++, i++)
+	if (INULL(*p)) {
+	    if (i < cs)
+		offs--;
+	    if (p[1] || *p != Bnull) {
+		if (*p == Bnull) {
+		    *tt = '\\';
+		    if (cs == i + 1)
+			cs++, offs++;
 		} else {
 		    ocs = cs;
-		    *tt = '\0';
-		    cs = we;
-		    backdel(1);
-		    if (ocs == we)
-			cs = we - 1;
-		    else
-			cs = ocs;
+		    cs = i;
+		    foredel(1);
+		    chuck(tt--);
+		    if ((cs = ocs) > i--)
+			cs--;
 		    we--;
 		}
-		chuck(p--);
+	    } else {
+		ocs = cs;
+		*tt = '\0';
+		cs = we;
+		backdel(1);
+		if (ocs == we)
+		    cs = we - 1;
+		else
+		    cs = ocs;
+		we--;
 	    }
+	    chuck(p--);
+	}
+
+    zsfree(origword);
+    origword = ztrdup(s);
 
-	zsfree(origword);
-	origword = ztrdup(s);
+    if (!isset(IGNOREBRACES)) {
+	/* Try and deal with foo{xxx etc. */
+	char *curs = s + (isset(COMPLETEINWORD) ? offs : strlen(s));
+	char *predup = dupstring(s), *dp = predup;
+	char *bbeg = NULL, *bend = NULL, *dbeg = NULL;
+	char *lastp = NULL, *firsts = NULL;
+	int cant = 0, begi = 0, boffs = offs, hascom = 0;
+
+	for (i = 0, p = s; *p; p++, dp++, i++) {
+	    /* careful, ${... is not a brace expansion...
+	     * we try to get braces after a parameter expansion right,
+	     * but this may fail sometimes. sorry.
+	     */
+	    if (*p == String || *p == Qstring) {
+		if (p[1] == Inbrace || p[1] == Inpar || p[1] == Inbrack) {
+		    char *tp = p + 1;
+
+		    if (skipparens(*tp, (*tp == Inbrace ? Outbrace :
+					 (*tp == Inpar ? Outpar : Outbrack)),
+				   &tp)) {
+			tt = NULL;
+			break;
+		    }
+		    i += tp - p;
+		    dp += tp - p;
+		    p = tp;
+		} else {
+		    char *tp = p + 1;
 
-	if (!isset(IGNOREBRACES)) {
-	    /* Try and deal with foo{xxx etc. */
-	    char *curs = s + (isset(COMPLETEINWORD) ? offs : strlen(s));
-	    char *predup = dupstring(s), *dp = predup;
-	    char *bbeg = NULL, *bend = NULL, *dbeg = NULL;
-	    char *lastp = NULL, *firsts = NULL;
-	    int cant = 0, begi = 0, boffs = offs, hascom = 0;
-
-	    for (i = 0, p = s; *p; p++, dp++, i++) {
-		/* careful, ${... is not a brace expansion...
-		 * we try to get braces after a parameter expansion right,
-		 * but this may fail sometimes. sorry.
-		 */
-		if (*p == String || *p == Qstring) {
-		    if (p[1] == Inbrace || p[1] == Inpar || p[1] == Inbrack) {
-			char *tp = p + 1;
-
-			if (skipparens(*tp, (*tp == Inbrace ? Outbrace :
-					     (*tp == Inpar ? Outpar : Outbrack)),
-				       &tp)) {
+		    for (; *tp == '^' || *tp == Hat ||
+			     *tp == '=' || *tp == Equals ||
+			     *tp == '~' || *tp == Tilde ||
+			     *tp == '#' || *tp == Pound || *tp == '+';
+			 tp++);
+		    if (*tp == Quest || *tp == Star || *tp == String ||
+			*tp == Qstring || *tp == '?' || *tp == '*' ||
+			*tp == '$' || *tp == '-' || *tp == '!' ||
+			*tp == '@')
+			p++, i++;
+		    else {
+			if (idigit(*tp))
+			    while (idigit(*tp))
+				tp++;
+			else if (iident(*tp))
+			    while (iident(*tp))
+				tp++;
+			else {
 			    tt = NULL;
 			    break;
 			}
+			if (*tp == Inbrace) {
+			    cant = 1;
+			    break;
+			}
+			tp--;
 			i += tp - p;
 			dp += tp - p;
 			p = tp;
-		    } else {
-			char *tp = p + 1;
-
-			for (; *tp == '^' || *tp == Hat ||
-				 *tp == '=' || *tp == Equals ||
-				 *tp == '~' || *tp == Tilde ||
-				 *tp == '#' || *tp == Pound || *tp == '+';
-			     tp++);
-			if (*tp == Quest || *tp == Star || *tp == String ||
-			    *tp == Qstring || *tp == '?' || *tp == '*' ||
-			    *tp == '$' || *tp == '-' || *tp == '!' ||
-			    *tp == '@')
-			    p++, i++;
-			else {
-			    if (idigit(*tp))
-				while (idigit(*tp))
-				    tp++;
-			    else if (iident(*tp))
-				while (iident(*tp))
-				    tp++;
-			    else {
-				tt = NULL;
-				break;
-			    }
-			    if (*tp == Inbrace) {
-				cant = 1;
-				break;
-			    }
-			    tp--;
-			    i += tp - p;
-			    dp += tp - p;
-			    p = tp;
-			}
 		    }
-		} else if (p < curs) {
-		    if (*p == Outbrace) {
-			cant = 1;
-			break;
-		    }
-		    if (*p == Inbrace) {
-			if (bbeg) {
-			    Brinfo new;
-			    int len = bend - bbeg;
-
-			    new = (Brinfo) zalloc(sizeof(*new));
-			    nbrbeg++;
-
-			    new->next = NULL;
-			    if (lastbrbeg)
-				lastbrbeg->next = new;
-			    else
-				brbeg = new;
-			    lastbrbeg = new;
-
-			    new->next = NULL;
-			    PERMALLOC {
-				new->str = dupstrpfx(bbeg, len);
-				untokenize(new->str);
-			    } LASTALLOC;
-			    new->pos = begi;
-			    *dbeg = '\0';
-			    new->qpos = strlen(quotename(predup, NULL));
-			    *dbeg = '{';
-			    i -= len;
-			    boffs -= len;
-			    strcpy(dbeg, dbeg + len);
-			    dp -= len;
-			}
-			bbeg = lastp = p;
-			dbeg = dp;
-			bend = p + 1;
-			begi = i;
-		    } else if (*p == Comma && bbeg) {
-			bend = p + 1;
-			hascom = 1;
-		    }
-		} else {
-		    if (*p == Inbrace) {
-			cant = 1;
-			break;
-		    }
-		    if (p == curs) {
-			if (bbeg) {
-			    Brinfo new;
-			    int len = bend - bbeg;
-
-			    new = (Brinfo) zalloc(sizeof(*new));
-			    nbrbeg++;
-
-			    new->next = NULL;
-			    if (lastbrbeg)
-				lastbrbeg->next = new;
-			    else
-				brbeg = new;
-			    lastbrbeg = new;
-
-			    PERMALLOC {
-				new->str = dupstrpfx(bbeg, len);
-				untokenize(new->str);
-			    } LASTALLOC;
-			    new->pos = begi;
-			    *dbeg = '\0';
-			    new->qpos = strlen(quotename(predup, NULL));
-			    *dbeg = '{';
-			    i -= len;
-			    boffs -= len;
-			    strcpy(dbeg, dbeg + len);
-			    dp -= len;
-			}
-			bbeg = NULL;
-		    }
-		    if (*p == Comma) {
-			if (!bbeg)
-			    bbeg = p;
-			hascom = 1;
-		    } else if (*p == Outbrace) {
+		}
+	    } else if (p < curs) {
+		if (*p == Outbrace) {
+		    cant = 1;
+		    break;
+		}
+		if (*p == Inbrace) {
+		    if (bbeg) {
 			Brinfo new;
-			int len;
+			int len = bend - bbeg;
 
-			if (!bbeg)
-			    bbeg = p;
-			len = p + 1 - bbeg;
-			if (!firsts)
-			    firsts = p + 1;
-			
 			new = (Brinfo) zalloc(sizeof(*new));
-			nbrend++;
-
-			if (!lastbrend)
-			    lastbrend = new;
+			nbrbeg++;
 
-			new->next = brend;
-			brend = new;
+			new->next = NULL;
+			if (lastbrbeg)
+			    lastbrbeg->next = new;
+			else
+			    brbeg = new;
+			lastbrbeg = new;
 
-			PERMALLOC {
-			    new->str = dupstrpfx(bbeg, len);
-			    untokenize(new->str);
-			} LASTALLOC;
-			new->pos = dp - predup - len + 1;
-			new->qpos = len;
-			bbeg = NULL;
+			new->next = NULL;
+			new->str = ztrduppfx(bbeg, len);
+			untokenize(new->str);
+			new->pos = begi;
+			*dbeg = '\0';
+			new->qpos = strlen(quotename(predup, NULL));
+			*dbeg = '{';
+			i -= len;
+			boffs -= len;
+			strcpy(dbeg, dbeg + len);
+			dp -= len;
 		    }
+		    bbeg = lastp = p;
+		    dbeg = dp;
+		    bend = p + 1;
+		    begi = i;
+		} else if (*p == Comma && bbeg) {
+		    bend = p + 1;
+		    hascom = 1;
 		}
-	    }
-	    if (cant) {
-		freebrinfo(brbeg);
-		freebrinfo(brend);
-		brbeg = lastbrbeg = brend = lastbrend = NULL;
-		nbrbeg = nbrend = 0;
 	    } else {
-		if (p == curs && bbeg) {
+		if (*p == Inbrace) {
+		    cant = 1;
+		    break;
+		}
+		if (p == curs) {
+		    if (bbeg) {
+			Brinfo new;
+			int len = bend - bbeg;
+
+			new = (Brinfo) zalloc(sizeof(*new));
+			nbrbeg++;
+
+			new->next = NULL;
+			if (lastbrbeg)
+			    lastbrbeg->next = new;
+			else
+			    brbeg = new;
+			lastbrbeg = new;
+
+			new->str = ztrduppfx(bbeg, len);
+			untokenize(new->str);
+			new->pos = begi;
+			*dbeg = '\0';
+			new->qpos = strlen(quotename(predup, NULL));
+			*dbeg = '{';
+			i -= len;
+			boffs -= len;
+			strcpy(dbeg, dbeg + len);
+			dp -= len;
+		    }
+		    bbeg = NULL;
+		}
+		if (*p == Comma) {
+		    if (!bbeg)
+			bbeg = p;
+		    hascom = 1;
+		} else if (*p == Outbrace) {
 		    Brinfo new;
-		    int len = bend - bbeg;
+		    int len;
+
+		    if (!bbeg)
+			bbeg = p;
+		    len = p + 1 - bbeg;
+		    if (!firsts)
+			firsts = p + 1;
 
 		    new = (Brinfo) zalloc(sizeof(*new));
-		    nbrbeg++;
+		    nbrend++;
 
-		    new->next = NULL;
-		    if (lastbrbeg)
-			lastbrbeg->next = new;
-		    else
-			brbeg = new;
-		    lastbrbeg = new;
+		    if (!lastbrend)
+			lastbrend = new;
 
-		    PERMALLOC {
-			new->str = dupstrpfx(bbeg, len);
-			untokenize(new->str);
-		    } LASTALLOC;
-		    new->pos = begi;
-		    *dbeg = '\0';
-		    new->qpos = strlen(quotename(predup, NULL));
-		    *dbeg = '{';
-		    boffs -= len;
-		    strcpy(dbeg, dbeg + len);
+		    new->next = brend;
+		    brend = new;
+
+		    new->str = ztrduppfx(bbeg, len);
+		    untokenize(new->str);
+		    new->pos = dp - predup - len + 1;
+		    new->qpos = len;
+		    bbeg = NULL;
 		}
-		if (brend) {
-		    Brinfo bp, prev = NULL;
-		    int p, l;
-
-		    for (bp = brend; bp; bp = bp->next) {
-			bp->prev = prev;
-			prev = bp;
-			p = bp->pos;
-			l = bp->qpos;
-			bp->pos = strlen(predup + p + l);
-			bp->qpos = strlen(quotename(predup + p + l, NULL));
-			strcpy(predup + p, predup + p + l);
-		    }
+	    }
+	}
+	if (cant) {
+	    freebrinfo(brbeg);
+	    freebrinfo(brend);
+	    brbeg = lastbrbeg = brend = lastbrend = NULL;
+	    nbrbeg = nbrend = 0;
+	} else {
+	    if (p == curs && bbeg) {
+		Brinfo new;
+		int len = bend - bbeg;
+
+		new = (Brinfo) zalloc(sizeof(*new));
+		nbrbeg++;
+
+		new->next = NULL;
+		if (lastbrbeg)
+		    lastbrbeg->next = new;
+		else
+		    brbeg = new;
+		lastbrbeg = new;
+
+		new->str = ztrduppfx(bbeg, len);
+		untokenize(new->str);
+		new->pos = begi;
+		*dbeg = '\0';
+		new->qpos = strlen(quotename(predup, NULL));
+		*dbeg = '{';
+		boffs -= len;
+		strcpy(dbeg, dbeg + len);
+	    }
+	    if (brend) {
+		Brinfo bp, prev = NULL;
+		int p, l;
+
+		for (bp = brend; bp; bp = bp->next) {
+		    bp->prev = prev;
+		    prev = bp;
+		    p = bp->pos;
+		    l = bp->qpos;
+		    bp->pos = strlen(predup + p + l);
+		    bp->qpos = strlen(quotename(predup + p + l, NULL));
+		    strcpy(predup + p, predup + p + l);
 		}
-		if (hascom) {
-		    if (lastp) {
-			char sav = *lastp;
-
-			*lastp = '\0';
-			untokenize(lastprebr = ztrdup(s));
-			*lastp = sav;
-		    }
-		    if ((lastpostbr = ztrdup(firsts)))
-			untokenize(lastpostbr);
+	    }
+	    if (hascom) {
+		if (lastp) {
+		    char sav = *lastp;
+
+		    *lastp = '\0';
+		    untokenize(lastprebr = ztrdup(s));
+		    *lastp = sav;
 		}
-		zsfree(s);
-		s = ztrdup(predup);
-		offs = boffs;
+		if ((lastpostbr = ztrdup(firsts)))
+		    untokenize(lastpostbr);
 	    }
+	    zsfree(s);
+	    s = ztrdup(predup);
+	    offs = boffs;
 	}
-    } LASTALLOC;
+    }
     lexrestore();
 
     return (char *)s;
@@ -1603,63 +1594,60 @@
     LinkList vl;
     char *ss;
 
-    DPUTS(useheap, "BUG: useheap in doexpansion()");
-    HEAPALLOC {
-	pushheap();
-	vl = newlinklist();
-	ss = dupstring(s);
-	addlinknode(vl, ss);
-	prefork(vl, 0);
-	if (errflag)
-	    goto end;
-	if (lst == COMP_LIST_EXPAND || lst == COMP_EXPAND) {
-	    int ng = opts[NULLGLOB];
-
-	    opts[NULLGLOB] = 1;
-	    globlist(vl, 1);
-	    opts[NULLGLOB] = ng;
-	}
-	if (errflag)
-	    goto end;
-	if (empty(vl) || !*(char *)peekfirst(vl))
-	    goto end;
-	if (peekfirst(vl) == (void *) ss ||
-		(olst == COMP_EXPAND_COMPLETE &&
-		 !nextnode(firstnode(vl)) && *s == Tilde &&
-		 (ss = dupstring(s), filesubstr(&ss, 0)) &&
-		 !strcmp(ss, (char *)peekfirst(vl)))) {
-	    /* If expansion didn't change the word, try completion if *
-	     * expandorcomplete was called, otherwise, just beep.     */
-	    if (lst == COMP_EXPAND_COMPLETE)
-		docompletion(s, COMP_COMPLETE, explincmd);
-	    goto end;
-	}
-	if (lst == COMP_LIST_EXPAND) {
-	    /* Only the list of expansions was requested. */
-	    ret = listlist(vl);
-	    showinglist = 0;
-	    goto end;
-	}
-	/* Remove the current word and put the expansions there. */
-	cs = wb;
-	foredel(we - wb);
-	while ((ss = (char *)ugetnode(vl))) {
-	    ret = 0;
-	    ss = quotename(ss, NULL);
-	    untokenize(ss);
-	    inststr(ss);
+    pushheap();
+    vl = newlinklist();
+    ss = dupstring(s);
+    addlinknode(vl, ss);
+    prefork(vl, 0);
+    if (errflag)
+	goto end;
+    if (lst == COMP_LIST_EXPAND || lst == COMP_EXPAND) {
+	int ng = opts[NULLGLOB];
+
+	opts[NULLGLOB] = 1;
+	globlist(vl, 1);
+	opts[NULLGLOB] = ng;
+    }
+    if (errflag)
+	goto end;
+    if (empty(vl) || !*(char *)peekfirst(vl))
+	goto end;
+    if (peekfirst(vl) == (void *) ss ||
+	(olst == COMP_EXPAND_COMPLETE &&
+	 !nextnode(firstnode(vl)) && *s == Tilde &&
+	 (ss = dupstring(s), filesubstr(&ss, 0)) &&
+	 !strcmp(ss, (char *)peekfirst(vl)))) {
+	/* If expansion didn't change the word, try completion if *
+	 * expandorcomplete was called, otherwise, just beep.     */
+	if (lst == COMP_EXPAND_COMPLETE)
+	    docompletion(s, COMP_COMPLETE, explincmd);
+	goto end;
+    }
+    if (lst == COMP_LIST_EXPAND) {
+	/* Only the list of expansions was requested. */
+	ret = listlist(vl);
+	showinglist = 0;
+	goto end;
+    }
+    /* Remove the current word and put the expansions there. */
+    cs = wb;
+    foredel(we - wb);
+    while ((ss = (char *)ugetnode(vl))) {
+	ret = 0;
+	ss = quotename(ss, NULL);
+	untokenize(ss);
+	inststr(ss);
 #if 0
-	    if (olst != COMP_EXPAND_COMPLETE || nonempty(vl) ||
-		(cs && line[cs-1] != '/')) {
+	if (olst != COMP_EXPAND_COMPLETE || nonempty(vl) ||
+	    (cs && line[cs-1] != '/')) {
 #endif
-	    if (nonempty(vl)) {
-		spaceinline(1);
-		line[cs++] = ' ';
-	    }
+	if (nonempty(vl)) {
+	    spaceinline(1);
+	    line[cs++] = ' ';
 	}
-      end:
-	popheap();
-    } LASTALLOC;
+    }
+    end:
+    popheap();
 
     return ret;
 }
@@ -2079,61 +2067,59 @@
     unsigned char *ol;
     int oll, ocs, ne = noerrs, err;
 
-    DPUTS(useheap, "BUG: useheap in doexpandhist()");
-    HEAPALLOC {
-	pushheap();
-	metafy_line();
-	oll = ll;
-	ocs = cs;
-	ol = (unsigned char *)dupstring((char *)line);
-	expanding = 1;
-	excs = cs;
-	ll = cs = 0;
-	lexsave();
-	/* We push ol as it will remain unchanged */
-	inpush((char *) ol, 0, NULL);
-	strinbeg(1);
-	noaliases = 1;
-	noerrs = 1;
-	exlast = inbufct;
-	do {
-	    ctxtlex();
-	} while (tok != ENDINPUT && tok != LEXERR);
-	while (!lexstop)
-	    hgetc();
-	/* We have to save errflags because it's reset in lexrestore. Since  *
-	 * noerrs was set to 1 errflag is true if there was a habort() which *
-	 * means that the expanded string is unusable.                       */
-	err = errflag;
-	noerrs = ne;
-	noaliases = 0;
-	strinend();
-	inpop();
-	zleparse = 0;
-	lexrestore();
-	expanding = 0;
+    pushheap();
+    metafy_line();
+    oll = ll;
+    ocs = cs;
+    ol = (unsigned char *)dupstring((char *)line);
+    expanding = 1;
+    excs = cs;
+    ll = cs = 0;
+    lexsave();
+    /* We push ol as it will remain unchanged */
+    inpush((char *) ol, 0, NULL);
+    strinbeg(1);
+    noaliases = 1;
+    noerrs = 1;
+    exlast = inbufct;
+    do {
+	ctxtlex();
+    } while (tok != ENDINPUT && tok != LEXERR);
+    while (!lexstop)
+	hgetc();
+    /* We have to save errflags because it's reset in lexrestore. Since  *
+     * noerrs was set to 1 errflag is true if there was a habort() which *
+     * means that the expanded string is unusable.                       */
+    err = errflag;
+    noerrs = ne;
+    noaliases = 0;
+    strinend();
+    inpop();
+    zleparse = 0;
+    lexrestore();
+    expanding = 0;
 
-	if (!err) {
-	    cs = excs;
-	    if (strcmp((char *)line, (char *)ol)) {
-		unmetafy_line();
-		/* For vi mode -- reset the beginning-of-insertion pointer   *
-		 * to the beginning of the line.  This seems a little silly, *
-		 * if we are, for example, expanding "exec !!".              */
-		if (viinsbegin > findbol())
-		    viinsbegin = findbol();
-		popheap();
-		LASTALLOC_RETURN 1;
-	    }
+    if (!err) {
+	cs = excs;
+	if (strcmp((char *)line, (char *)ol)) {
+	    unmetafy_line();
+	    /* For vi mode -- reset the beginning-of-insertion pointer   *
+	     * to the beginning of the line.  This seems a little silly, *
+	     * if we are, for example, expanding "exec !!".              */
+	    if (viinsbegin > findbol())
+		viinsbegin = findbol();
+	    popheap();
+	    return 1;
 	}
+    }
+
+    strcpy((char *)line, (char *)ol);
+    ll = oll;
+    cs = ocs;
+    unmetafy_line();
 
-	strcpy((char *)line, (char *)ol);
-	ll = oll;
-	cs = ocs;
-	unmetafy_line();
+    popheap();
 
-	popheap();
-    } LASTALLOC;
     return 0;
 }
 
@@ -2166,34 +2152,32 @@
     int curlincmd;
     char *s = NULL;
 
-    DPUTS(useheap, "BUG: useheap in getcurcmd()");
-    HEAPALLOC {
-	zleparse = 2;
-	lexsave();
-	metafy_line();
-	inpush(dupstrspace((char *) line), 0, NULL);
-	unmetafy_line();
-	strinbeg(1);
-	pushheap();
-	do {
-	    curlincmd = incmdpos;
-	    ctxtlex();
-	    if (tok == ENDINPUT || tok == LEXERR)
-		break;
-	    if (tok == STRING && curlincmd) {
-		zsfree(s);
-		s = ztrdup(tokstr);
-		cmdwb = ll - wordbeg;
-		cmdwe = ll + 1 - inbufct;
-	    }
+    zleparse = 2;
+    lexsave();
+    metafy_line();
+    inpush(dupstrspace((char *) line), 0, NULL);
+    unmetafy_line();
+    strinbeg(1);
+    pushheap();
+    do {
+	curlincmd = incmdpos;
+	ctxtlex();
+	if (tok == ENDINPUT || tok == LEXERR)
+	    break;
+	if (tok == STRING && curlincmd) {
+	    zsfree(s);
+	    s = ztrdup(tokstr);
+	    cmdwb = ll - wordbeg;
+	    cmdwe = ll + 1 - inbufct;
 	}
-	while (tok != ENDINPUT && tok != LEXERR && zleparse);
-	popheap();
-	strinend();
-	inpop();
-	errflag = zleparse = 0;
-	lexrestore();
-    } LASTALLOC;
+    }
+    while (tok != ENDINPUT && tok != LEXERR && zleparse);
+    popheap();
+    strinend();
+    inpop();
+    errflag = zleparse = 0;
+    lexrestore();
+
     return s;
 }
 
@@ -2213,9 +2197,9 @@
     inststr(bindk->nam);
     inststr(" ");
     untokenize(s);
-    HEAPALLOC {
-	inststr(quotename(s, NULL));
-    } LASTALLOC;
+
+    inststr(quotename(s, NULL));
+
     zsfree(s);
     done = 1;
     return 0;
diff -ru ../z.old/Src/Zle/zleparameter.c Src/Zle/zleparameter.c
--- ../z.old/Src/Zle/zleparameter.c	Wed Feb 23 14:22:10 2000
+++ Src/Zle/zleparameter.c	Wed Feb 23 14:23:56 2000
@@ -100,27 +100,24 @@
     Param pm = NULL;
     Thingy th;
 
-    HEAPALLOC {
-	pm = (Param) zhalloc(sizeof(struct param));
-	pm->nam = dupstring(name);
-	pm->flags = PM_SCALAR | PM_READONLY;
-	pm->sets.cfn = NULL;
-	pm->gets.cfn = strgetfn;
-	pm->unsetfn = NULL;
-	pm->ct = 0;
-	pm->env = NULL;
-	pm->ename = NULL;
-	pm->old = NULL;
-	pm->level = 0;
-	if ((th = (Thingy) thingytab->getnode(thingytab, name)) &&
-	    !(th->flags & DISABLED))
-	    pm->u.str = widgetstr(th->widget);
-	else {
-	    pm->u.str = dupstring("");
-	    pm->flags |= PM_UNSET;
-	}
-    } LASTALLOC;
-
+    pm = (Param) zhalloc(sizeof(struct param));
+    pm->nam = dupstring(name);
+    pm->flags = PM_SCALAR | PM_READONLY;
+    pm->sets.cfn = NULL;
+    pm->gets.cfn = strgetfn;
+    pm->unsetfn = NULL;
+    pm->ct = 0;
+    pm->env = NULL;
+    pm->ename = NULL;
+    pm->old = NULL;
+    pm->level = 0;
+    if ((th = (Thingy) thingytab->getnode(thingytab, name)) &&
+	!(th->flags & DISABLED))
+	pm->u.str = widgetstr(th->widget);
+    else {
+	pm->u.str = dupstring("");
+	pm->flags |= PM_UNSET;
+    }
     return (HashNode) pm;
 }
 
diff -ru ../z.old/Src/builtin.c Src/builtin.c
--- ../z.old/Src/builtin.c	Wed Feb 23 14:22:02 2000
+++ Src/builtin.c	Wed Feb 23 14:23:56 2000
@@ -548,9 +548,7 @@
     } else {
 	/* set shell arguments */
 	freearray(pparams);
-	PERMALLOC {
-	    pparams = arrdup(args);
-	} LASTALLOC;
+	pparams = zarrdup(args);
     }
     return 0;
 }
@@ -609,15 +607,13 @@
 	return 0;
     }
     /* replace the stack with the specified directories */
-    PERMALLOC {
-	l = newlinklist();
-	if (*argv) {
-	    while (*argv)
-		addlinknode(l, ztrdup(*argv++));
-	    freelinklist(dirstack, freestr);
-	    dirstack = l;
-	}
-    } LASTALLOC;
+    l = znewlinklist();
+    if (*argv) {
+	while (*argv)
+	    zaddlinknode(l, ztrdup(*argv++));
+	freelinklist(dirstack, freestr);
+	dirstack = l;
+    }
     return 0;
 }
 
@@ -699,13 +695,11 @@
     }
   brk:
     chasinglinks = ops['P'] || (isset(CHASELINKS) && !ops['L']);
-    PERMALLOC {
-	pushnode(dirstack, ztrdup(pwd));
-	if (!(dir = cd_get_dest(nam, argv, ops, func))) {
-	    zsfree(getlinknode(dirstack));
-	    LASTALLOC_RETURN 1;
-	}
-    } LASTALLOC;
+    zpushnode(dirstack, ztrdup(pwd));
+    if (!(dir = cd_get_dest(nam, argv, ops, func))) {
+	zsfree(getlinknode(dirstack));
+	return 1;
+    }
     cd_new_pwd(func, dir);
 
     if (stat(unmeta(pwd), &st1) < 0) {
@@ -744,9 +738,9 @@
 	if (func == BIN_PUSHD && unset(PUSHDTOHOME))
 	    dir = nextnode(firstnode(dirstack));
 	if (dir)
-	    insertlinknode(dirstack, dir, getlinknode(dirstack));
+	    zinsertlinknode(dirstack, dir, getlinknode(dirstack));
 	else if (func != BIN_POPD)
-	    pushnode(dirstack, ztrdup(home));
+	    zpushnode(dirstack, ztrdup(home));
     } else if (!argv[1]) {
 	int dd;
 	char *end;
@@ -767,8 +761,8 @@
 	    }
 	}
 	if (!dir)
-	    pushnode(dirstack, ztrdup(strcmp(argv[0], "-")
-				      ? (doprintdir--, argv[0]) : oldpwd));
+	    zpushnode(dirstack, ztrdup(strcmp(argv[0], "-")
+				       ? (doprintdir--, argv[0]) : oldpwd));
     } else {
 	char *u, *d;
 	int len1, len2, len3;
@@ -784,7 +778,7 @@
 	strncpy(d, pwd, len3);
 	strcpy(d + len3, argv[1]);
 	strcat(d, u + len1);
-	pushnode(dirstack, d);
+	zpushnode(dirstack, d);
 	doprintdir++;
     }
 
@@ -1219,7 +1213,7 @@
 	remhist();
     /* put foo=bar type arguments into the substitution list */
     while (*argv && equalsplit(*argv, &s)) {
-	Asgment a = (Asgment) alloc(sizeof *a);
+	Asgment a = (Asgment) zhalloc(sizeof *a);
 
 	if (!asgf)
 	    asgf = asgl = a;
@@ -1353,7 +1347,7 @@
 	oldpos = s;
 	/* loop over occurences of oldstr in s, replacing them with newstr */
 	while ((newpos = (char *)strstr(oldpos, oldstr))) {
-	    newmem = (char *) alloc(1 + (newpos - s)
+	    newmem = (char *) zhalloc(1 + (newpos - s)
 			+ strlen(newstr) + strlen(newpos + strlen(oldstr)));
 	    ztrncpy(newmem, s, newpos - s);
 	    strcat(newmem, newstr);
@@ -1761,26 +1755,24 @@
 	 * We need to use the special setting function to re-initialise
 	 * the special parameter to empty.
 	 */
-	HEAPALLOC {
-	    switch (PM_TYPE(pm->flags)) {
-	    case PM_SCALAR:
-		pm->sets.cfn(pm, ztrdup(""));
-		break;
-	    case PM_INTEGER:
-		pm->sets.ifn(pm, 0);
-		break;
-	    case PM_EFLOAT:
-	    case PM_FFLOAT:
-		pm->sets.ffn(pm, 0.0);
-		break;
-	    case PM_ARRAY:
-		pm->sets.afn(pm, mkarray(NULL));
-		break;
-	    case PM_HASHED:
-		pm->sets.hfn(pm, newparamtable(17, pm->nam));
-		break;
-	    }
-	} LASTALLOC;
+	switch (PM_TYPE(pm->flags)) {
+	case PM_SCALAR:
+	    pm->sets.cfn(pm, ztrdup(""));
+	    break;
+	case PM_INTEGER:
+	    pm->sets.ifn(pm, 0);
+	    break;
+	case PM_EFLOAT:
+	case PM_FFLOAT:
+	    pm->sets.ffn(pm, 0.0);
+	    break;
+	case PM_ARRAY:
+	    pm->sets.afn(pm, mkarray(NULL));
+	    break;
+	case PM_HASHED:
+	    pm->sets.hfn(pm, newparamtable(17, pm->nam));
+	    break;
+	}
     }
     pm->flags |= (on & PM_READONLY);
     if (value && (pm->flags & (PM_ARRAY|PM_HASHED))) {
@@ -1944,7 +1936,6 @@
 
     /* With the -m option, treat arguments as glob patterns */
     if (ops['m']) {
-	MUSTUSEHEAP("typeset -m");
 	while ((asg = getasg(*argv++))) {
 	    LinkList pmlist = newlinklist();
 	    LinkNode pmnode;
@@ -2739,7 +2730,7 @@
     }
     /* compute lengths, and interpret according to -P, -D, -e, etc. */
     argc = arrlen(args);
-    len = (int *)ncalloc(argc * sizeof(int));
+    len = (int *) hcalloc(argc * sizeof(int));
     for(n = 0; n < argc; n++) {
 	/* first \ sequences */
 	if (!ops['e'] && (ops['R'] || ops['r'] || ops['E']))
@@ -2763,7 +2754,7 @@
 	if(ops['D']) {
 	    Nameddir d = finddir(args[n]);
 	    if(d) {
-		char *arg = alloc(strlen(args[n]) + 1);
+		char *arg = zhalloc(strlen(args[n]) + 1);
 		sprintf(arg, "~%s%s", d->nam,
 			args[n] + strlen(d->dir));
 		args[n] = arg;
@@ -2774,9 +2765,7 @@
 
     /* -z option -- push the arguments onto the editing buffer stack */
     if (ops['z']) {
-	PERMALLOC {
-	    pushnode(bufstack, sepjoin(args, NULL));
-	} LASTALLOC;
+	zpushnode(bufstack, sepjoin(args, NULL, 0));
 	return 0;
     }
     /* -s option -- add the arguments to the history list */
@@ -2784,26 +2773,24 @@
 	int nwords = 0, nlen, iwords;
 	char **pargs = args;
 
-	PERMALLOC {
-	    ent = prepnexthistent(++curhist);
-	    while (*pargs++)
-		nwords++;
-	    if ((ent->nwords = nwords)) {
-		ent->words = (short *)zalloc(nwords*2*sizeof(short));
-		nlen = iwords = 0;
-		for (pargs = args; *pargs; pargs++) {
-		    ent->words[iwords++] = nlen;
-		    nlen += strlen(*pargs);
-		    ent->words[iwords++] = nlen;
-		    nlen++;
-		}
-	    } else
-		ent->words = (short *)NULL;
-	    ent->text = zjoin(args, ' ');
-	    ent->stim = ent->ftim = time(NULL);
-	    ent->flags = 0;
-	    addhistnode(histtab, ent->text, ent);
-	} LASTALLOC;
+	ent = prepnexthistent(++curhist);
+	while (*pargs++)
+	    nwords++;
+	if ((ent->nwords = nwords)) {
+	    ent->words = (short *)zalloc(nwords*2*sizeof(short));
+	    nlen = iwords = 0;
+	    for (pargs = args; *pargs; pargs++) {
+		ent->words[iwords++] = nlen;
+		nlen += strlen(*pargs);
+		ent->words[iwords++] = nlen;
+		nlen++;
+	    }
+	} else
+	    ent->words = (short *)NULL;
+	ent->text = zjoin(args, ' ', 0);
+	ent->stim = ent->ftim = time(NULL);
+	ent->flags = 0;
+	addhistnode(histtab, ent->text, ent);
 	return 0;
     }
     /* -u and -p -- output to other than standard output */
@@ -2985,9 +2972,7 @@
 		    ret++;
 		    continue;
 		}
-                PERMALLOC {
-		    s = arrdup(s + num);
-                } LASTALLOC;
+		s = zarrdup(s + num);
                 setaparam(*argv, s);
             }
     } else {
@@ -3197,42 +3182,40 @@
 {
     static int in_exit;
 
-    HEAPALLOC {
-	if (isset(MONITOR) && !stopmsg && !from_signal) {
-	    scanjobs();    /* check if jobs need printing           */
-	    if (isset(CHECKJOBS))
-	        checkjobs();   /* check if any jobs are running/stopped */
-	    if (stopmsg) {
-		stopmsg = 2;
-		LASTALLOC_RETURN;
-	    }
-	}
-	if (in_exit++ && from_signal) {
+    if (isset(MONITOR) && !stopmsg && !from_signal) {
+	scanjobs();    /* check if jobs need printing           */
+	if (isset(CHECKJOBS))
+	    checkjobs();   /* check if any jobs are running/stopped */
+	if (stopmsg) {
+	    stopmsg = 2;
 	    LASTALLOC_RETURN;
 	}
-	if (isset(MONITOR)) {
-	    /* send SIGHUP to any jobs left running  */
-	    killrunjobs(from_signal);
-	}
-	if (isset(RCS) && interact) {
-	    if (!nohistsave)
-		savehistfile(NULL, 1, HFILE_USE_OPTIONS);
-	    if (islogin && !subsh) {
-		sourcehome(".zlogout");
+    }
+    if (in_exit++ && from_signal)
+	    return;
+
+    if (isset(MONITOR)) {
+	/* send SIGHUP to any jobs left running  */
+	killrunjobs(from_signal);
+    }
+    if (isset(RCS) && interact) {
+	if (!nohistsave)
+	    savehistfile(NULL, 1, HFILE_USE_OPTIONS);
+	if (islogin && !subsh) {
+	    sourcehome(".zlogout");
 #ifdef GLOBAL_ZLOGOUT
-		if (isset(RCS) && isset(GLOBALRCS))
-		    source(GLOBAL_ZLOGOUT);
+	    if (isset(RCS) && isset(GLOBALRCS))
+		source(GLOBAL_ZLOGOUT);
 #endif
-	    }
 	}
-	if (sigtrapped[SIGEXIT])
-	    dotrap(SIGEXIT);
-	runhookdef(EXITHOOK, NULL);
-	if (mypid != getpid())
-	    _exit(val);
-	else
-	    exit(val);
-    } LASTALLOC;
+    }
+    if (sigtrapped[SIGEXIT])
+	dotrap(SIGEXIT);
+    runhookdef(EXITHOOK, NULL);
+    if (mypid != getpid())
+	_exit(val);
+    else
+	exit(val);
 }
 
 /* . (dot), source */
@@ -3251,11 +3234,9 @@
 	return 0;
     old = pparams;
     /* get arguments for the script */
-    if (argv[1]) {
-	PERMALLOC {
-	    pparams = arrdup(argv + 1);
-	} LASTALLOC;
-    }
+    if (argv[1])
+	pparams = zarrdup(argv + 1);
+
     enam = arg0 = ztrdup(*argv);
     if (isset(FUNCTIONARGZERO)) {
 	old0 = argzero;
@@ -3336,7 +3317,7 @@
 {
     Eprog prog;
 
-    prog = parse_string(zjoin(argv, ' '), 0);
+    prog = parse_string(zjoin(argv, ' ', 1), 0);
     if (!prog) {
 	errflag = 0;
 	return 1;
@@ -3906,9 +3887,7 @@
 	    zwarnnam(name, "undefined signal: %s", *argv, 0);
 	    break;
 	}
-	PERMALLOC {
-	    t = dupeprog(prog);
-	} LASTALLOC;
+	t = zdupeprog(prog);
 	if (settrap(sig, t))
 	    freeeprog(t);
     }
diff -ru ../z.old/Src/cond.c Src/cond.c
--- ../z.old/Src/cond.c	Wed Feb 23 14:22:02 2000
+++ Src/cond.c	Wed Feb 23 14:23:56 2000
@@ -420,7 +420,7 @@
 tracemodcond(char *name, char **args, int inf)
 {
     char **aptr;
-    MUSTUSEHEAP("tracemodcond");
+
     args = arrdup(args);
     for (aptr = args; *aptr; aptr++)
 	untokenize(*aptr);
diff -ru ../z.old/Src/exec.c Src/exec.c
--- ../z.old/Src/exec.c	Wed Feb 23 14:22:02 2000
+++ Src/exec.c	Wed Feb 23 14:23:57 2000
@@ -1237,7 +1237,7 @@
     char **argv, **ptr;
 
     /* A bigger argv is necessary for executing scripts */
-    ptr = argv = 2 + (char **) ncalloc((countlinknodes(list) + 4) *
+    ptr = argv = 2 + (char **) hcalloc((countlinknodes(list) + 4) *
 				       sizeof(char *));
 
     if (isset(XTRACE)) {
@@ -1402,7 +1402,7 @@
 
     if (!mfds[fd1] || unset(MULTIOS)) {
 	if(!mfds[fd1]) {		/* starting a new multio */
-	    mfds[fd1] = (struct multio *) alloc(sizeof(struct multio));
+	    mfds[fd1] = (struct multio *) zhalloc(sizeof(struct multio));
 	    if (!forked && save[fd1] == -2)
 		save[fd1] = (fd1 == fd2) ? -1 : movefd(fd1);
 	}
@@ -2326,8 +2326,6 @@
     char *s;
     wordcode ac;
 
-    MUSTUSEHEAP("save_params()");
-    
     *restore_p = newlinklist();
     *remove_p = newlinklist();
 
@@ -2338,7 +2336,7 @@
 		paramtab->removenode(paramtab, s);
 	    } else if (!(pm->flags & PM_READONLY) &&
 		       (unset(RESTRICTED) || !(pm->flags & PM_RESTRICTED))) {
-		Param tpm = (Param) alloc(sizeof *tpm);
+		Param tpm = (Param) zhalloc(sizeof *tpm);
 		tpm->nam = s;
 		copyparam(tpm, pm, 1);
 		pm = tpm;
@@ -2671,7 +2669,7 @@
 
     fin = fdopen(in, "r");
     ret = newlinklist();
-    ptr = buf = (char *) ncalloc(bsiz = 64);
+    ptr = buf = (char *) hcalloc(bsiz = 64);
     while ((c = fgetc(fin)) != EOF || errno == EINTR) {
 	if (c == EOF) {
 	    errno = 0;
@@ -2684,7 +2682,7 @@
 	    cnt++;
 	}
 	if (++cnt >= bsiz) {
-	    char *pp = (char *) ncalloc(bsiz *= 2);
+	    char *pp = (char *) hcalloc(bsiz *= 2);
 
 	    memcpy(pp, buf, cnt - 1);
 	    ptr = (buf = pp) + cnt - 1;
@@ -2702,7 +2700,7 @@
 	}
 	addlinknode(ret, buf);
     } else {
-	char **words = spacesplit(buf, 0);
+	char **words = spacesplit(buf, 0, 1);
 
 	while (*words) {
 	    if (isset(GLOBSUBST))
@@ -2752,11 +2750,11 @@
 	return NULL;
 
     nam = ztrdup(nam);
-    PERMALLOC {
-	if (!jobtab[thisjob].filelist)
-	    jobtab[thisjob].filelist = newlinklist();
-	addlinknode(jobtab[thisjob].filelist, nam);
-    } LASTALLOC;
+
+    if (!jobtab[thisjob].filelist)
+	jobtab[thisjob].filelist = znewlinklist();
+    zaddlinknode(jobtab[thisjob].filelist, nam);
+
     child_block();
     fd = open(nam, O_WRONLY | O_CREAT | O_EXCL | O_NOCTTY, 0600);
 
@@ -2830,16 +2828,15 @@
     if (!(pnam = namedpipe()))
 	return NULL;
 #else
-    pnam = ncalloc(strlen(PATH_DEV_FD) + 6);
+    pnam = hcalloc(strlen(PATH_DEV_FD) + 6);
 #endif
     if (!(prog = parsecmd(cmd)))
 	return NULL;
 #ifndef PATH_DEV_FD
-    PERMALLOC {
-	if (!jobtab[thisjob].filelist)
-	    jobtab[thisjob].filelist = newlinklist();
-	addlinknode(jobtab[thisjob].filelist, ztrdup(pnam));
-    } LASTALLOC;
+    if (!jobtab[thisjob].filelist)
+	jobtab[thisjob].filelist = znewlinklist();
+    zaddlinknode(jobtab[thisjob].filelist, ztrdup(pnam));
+
     if (zfork()) {
 #else
     mpipe(pipes);
@@ -3024,40 +3021,37 @@
     if (htok)
 	execsubst(names);
 
-    PERMALLOC {
-	while ((s = (char *) ugetnode(names))) {
-	    prog = (Eprog) zalloc(sizeof(*prog));
-	    prog->heap = 0;
-	    prog->len = len;
-	    prog->npats = npats;
-	    prog->pats = pp = (Patprog *) zalloc(len);
-	    prog->prog = (Wordcode) (prog->pats + npats);
-	    for (i = npats; i--; pp++)
-		*pp = dummy_patprog1;
-	    memcpy(prog->prog, state->pc, plen);
-	    prog->strs = (char *) (prog->prog + nprg);
-	    prog->shf = NULL;
-
-	    shf = (Shfunc) zalloc(sizeof(*shf));
-	    shf->funcdef = prog;
-	    shf->flags = 0;
-
-	    /* is this shell function a signal trap? */
-	    if (!strncmp(s, "TRAP", 4) &&
-		(signum = getsignum(s + 4)) != -1) {
-		if (settrap(signum, shf->funcdef)) {
-		    freeeprog(shf->funcdef);
-		    zfree(shf, sizeof(*shf));
-		    state->pc = end;
-		    LASTALLOC_RETURN 1;
-		}
-		sigtrapped[signum] |= ZSIG_FUNC;
+    while ((s = (char *) ugetnode(names))) {
+	prog = (Eprog) zalloc(sizeof(*prog));
+	prog->heap = 0;
+	prog->len = len;
+	prog->npats = npats;
+	prog->pats = pp = (Patprog *) zalloc(len);
+	prog->prog = (Wordcode) (prog->pats + npats);
+	for (i = npats; i--; pp++)
+	    *pp = dummy_patprog1;
+	memcpy(prog->prog, state->pc, plen);
+	prog->strs = (char *) (prog->prog + nprg);
+	prog->shf = NULL;
+
+	shf = (Shfunc) zalloc(sizeof(*shf));
+	shf->funcdef = prog;
+	shf->flags = 0;
+
+	/* is this shell function a signal trap? */
+	if (!strncmp(s, "TRAP", 4) &&
+	    (signum = getsignum(s + 4)) != -1) {
+	    if (settrap(signum, shf->funcdef)) {
+		freeeprog(shf->funcdef);
+		zfree(shf, sizeof(*shf));
+		state->pc = end;
+		return 1;
 	    }
-	    shfunctab->addnode(shfunctab, ztrdup(s), shf);
+	    sigtrapped[signum] |= ZSIG_FUNC;
 	}
-    } LASTALLOC;
-
-    if(isset(HISTNOFUNCTIONS))
+	shfunctab->addnode(shfunctab, ztrdup(s), shf);
+    }
+    if (isset(HISTNOFUNCTIONS))
 	remhist();
     state->pc = end;
     return 0;
@@ -3150,9 +3144,7 @@
 	}
     } else {
 	freeeprog(shf->funcdef);
-	PERMALLOC {
-	    shf->funcdef = dupeprog(stripkshdef(prog, shf->nam));
-	} LASTALLOC;
+	shf->funcdef = zdupeprog(stripkshdef(prog, shf->nam));
 	shf->flags &= ~PM_UNDEFINED;
     }
     popheap();
@@ -3182,9 +3174,7 @@
     }
     if (!prog)
 	prog = &dummy_eprog;
-    PERMALLOC {
-	shf->funcdef = dupeprog(stripkshdef(prog, shf->nam));
-    } LASTALLOC;
+    shf->funcdef = zdupeprog(stripkshdef(prog, shf->nam));
     shf->flags &= ~PM_UNDEFINED;
 
     popheap();
@@ -3207,89 +3197,87 @@
     int obreaks = breaks;
     struct funcstack fstack;
 
-    HEAPALLOC {
-	pushheap();
-	if (trapreturn < 0)
-	    trapreturn--;
-	oldlastval = lastval;
-
-	starttrapscope();
-
-	tab = pparams;
-	oldscriptname = scriptname;
-	scriptname = dupstring(name);
-	oldzoptind = zoptind;
-	zoptind = 1;
-	oldoptcind = optcind;
-	optcind = 0;
-
-	/* We need to save the current options even if LOCALOPTIONS is *
-	 * not currently set.  That's because if it gets set in the    *
-	 * function we need to restore the original options on exit.   */
-	memcpy(saveopts, opts, sizeof(opts));
-
-	if (flags & PM_TAGGED)
-	    opts[XTRACE] = 1;
-	opts[PRINTEXITVALUE] = 0;
-	if (doshargs) {
-	    LinkNode node;
-
-	    node = doshargs->first;
-	    pparams = x = (char **) zcalloc(((sizeof *x) *
-					     (1 + countlinknodes(doshargs))));
-	    if (isset(FUNCTIONARGZERO)) {
-		oargv0 = argzero;
-		argzero = ztrdup((char *) node->dat);
-	    }
-	    node = node->next;
-	    for (; node; node = node->next, x++)
-		*x = ztrdup((char *) node->dat);
-	} else {
-	    pparams = (char **) zcalloc(sizeof *pparams);
-	    if (isset(FUNCTIONARGZERO)) {
-		oargv0 = argzero;
-		argzero = ztrdup(argzero);
-	    }
-	}
-	fstack.name = dupstring(name);
-	fstack.prev = funcstack;
-	funcstack = &fstack;
-	runshfunc(prog, wrappers, fstack.name);
-	funcstack = fstack.prev;
-	if (retflag) {
-	    retflag = 0;
-	    breaks = obreaks;
-	}
-	freearray(pparams);
-	if (oargv0) {
-	    zsfree(argzero);
-	    argzero = oargv0;
-	}
-	optcind = oldoptcind;
-	zoptind = oldzoptind;
-	scriptname = oldscriptname;
-	pparams = tab;
-
-	if (isset(LOCALOPTIONS)) {
-	    /* restore all shell options except PRIVILEGED and RESTRICTED */
-	    saveopts[PRIVILEGED] = opts[PRIVILEGED];
-	    saveopts[RESTRICTED] = opts[RESTRICTED];
-	    memcpy(opts, saveopts, sizeof(opts));
-	} else {
-	    /* just restore a couple. */
-	    opts[XTRACE] = saveopts[XTRACE];
-	    opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE];
-	    opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS];
-	}
+    pushheap();
+    if (trapreturn < 0)
+	trapreturn--;
+    oldlastval = lastval;
+
+    starttrapscope();
+
+    tab = pparams;
+    oldscriptname = scriptname;
+    scriptname = dupstring(name);
+    oldzoptind = zoptind;
+    zoptind = 1;
+    oldoptcind = optcind;
+    optcind = 0;
+
+    /* We need to save the current options even if LOCALOPTIONS is *
+     * not currently set.  That's because if it gets set in the    *
+     * function we need to restore the original options on exit.   */
+    memcpy(saveopts, opts, sizeof(opts));
+
+    if (flags & PM_TAGGED)
+	opts[XTRACE] = 1;
+    opts[PRINTEXITVALUE] = 0;
+    if (doshargs) {
+	LinkNode node;
+
+	node = doshargs->first;
+	pparams = x = (char **) zcalloc(((sizeof *x) *
+					 (1 + countlinknodes(doshargs))));
+	if (isset(FUNCTIONARGZERO)) {
+	    oargv0 = argzero;
+	    argzero = ztrdup((char *) node->dat);
+	}
+	node = node->next;
+	for (; node; node = node->next, x++)
+	    *x = ztrdup((char *) node->dat);
+    } else {
+	pparams = (char **) zcalloc(sizeof *pparams);
+	if (isset(FUNCTIONARGZERO)) {
+	    oargv0 = argzero;
+	    argzero = ztrdup(argzero);
+	}
+    }
+    fstack.name = dupstring(name);
+    fstack.prev = funcstack;
+    funcstack = &fstack;
+    runshfunc(prog, wrappers, fstack.name);
+    funcstack = fstack.prev;
+    if (retflag) {
+	retflag = 0;
+	breaks = obreaks;
+    }
+    freearray(pparams);
+    if (oargv0) {
+	zsfree(argzero);
+	argzero = oargv0;
+    }
+    optcind = oldoptcind;
+    zoptind = oldzoptind;
+    scriptname = oldscriptname;
+    pparams = tab;
+
+    if (isset(LOCALOPTIONS)) {
+	/* restore all shell options except PRIVILEGED and RESTRICTED */
+	saveopts[PRIVILEGED] = opts[PRIVILEGED];
+	saveopts[RESTRICTED] = opts[RESTRICTED];
+	memcpy(opts, saveopts, sizeof(opts));
+    } else {
+	/* just restore a couple. */
+	opts[XTRACE] = saveopts[XTRACE];
+	opts[PRINTEXITVALUE] = saveopts[PRINTEXITVALUE];
+	opts[LOCALOPTIONS] = saveopts[LOCALOPTIONS];
+    }
 
-	endtrapscope();
-
-	if (trapreturn < -1)
-	    trapreturn++;
-	if (noreturnval)
-	    lastval = oldlastval;
-	popheap();
-    } LASTALLOC;
+    endtrapscope();
+
+    if (trapreturn < -1)
+	trapreturn++;
+    if (noreturnval)
+	lastval = oldlastval;
+    popheap();
 }
 
 /* This finally executes a shell function and any function wrappers     *
@@ -3354,9 +3342,8 @@
 		    close(fd);
 		    d[len] = '\0';
 		    d = metafy(d, len, META_REALLOC);
-		    HEAPALLOC {
-			r = parse_string(d, 1);
-		    } LASTALLOC;
+
+		    r = parse_string(d, 1);
 
 		    zfree(d, len + 1);
 
diff -ru ../z.old/Src/glob.c Src/glob.c
--- ../z.old/Src/glob.c	Wed Feb 23 14:22:03 2000
+++ Src/glob.c	Wed Feb 23 14:23:57 2000
@@ -296,7 +296,7 @@
 	if (gf_listtypes || S_ISDIR(mode)) {
 	    int ll = strlen(s);
 
-	    news = (char *)ncalloc(ll + 2);
+	    news = (char *) hcalloc(ll + 2);
 	    strcpy(news, s);
 	    news[ll] = file_type(mode);
 	    news[ll + 1] = '\0';
@@ -625,7 +625,7 @@
 	instr += (3 + follow);
 
 	/* Now get the next path component if there is one. */
-	l1 = (Complist) alloc(sizeof *l1);
+	l1 = (Complist) zhalloc(sizeof *l1);
 	if ((l1->next = parsecomplist(instr)) == NULL) {
 	    errflag = 1;
 	    return NULL;
@@ -650,7 +650,7 @@
 		pdflag = 1;
 		instr++;
 	    }
-	    l1 = (Complist) alloc(sizeof *l1);
+	    l1 = (Complist) zhalloc(sizeof *l1);
 	    l1->pat = p1;
 	    l1->closure = 1 + pdflag;
 	    l1->follow = 0;
@@ -665,7 +665,7 @@
 	if (*instr == '/' || !*instr) {
 	    int ef = *instr == '/';
 
-	    l1 = (Complist) alloc(sizeof *l1);
+	    l1 = (Complist) zhalloc(sizeof *l1);
 	    l1->pat = p1;
 	    l1->closure = 0;
 	    l1->next = ef ? parsecomplist(instr+1) : NULL;
@@ -885,7 +885,6 @@
 				        /* return */
     struct globdata saved;		/* saved glob state              */
 
-    MUSTUSEHEAP("glob");
     if (unset(GLOBOPT) || !haswilds(ostr)) {
 	if (!nountok)
 	    untokenize(ostr);
@@ -1611,7 +1610,7 @@
 	while ((nam = (char *)ugetnode(&fake))) {
 	    /* Loop over matches, duplicating the *
 	     * redirection for each file found.   */
-	    ff = (struct redir *)alloc(sizeof *ff);
+	    ff = (struct redir *) zhalloc(sizeof *ff);
 	    *ff = *fn;
 	    ff->name = nam;
 	    addlinknode(tab, ff);
@@ -1755,12 +1754,12 @@
 	    if (*p) {
 		c1 = p - ccl;
 		if (imeta(c1)) {
-		    str = ncalloc(len + 1);
+		    str = hcalloc(len + 1);
 		    str[pl] = Meta;
 		    str[pl+1] = c1 ^ 32;
 		    strcpy(str + pl + 2, str2);
 		} else {
-		    str = ncalloc(len);
+		    str = hcalloc(len);
 		    str[pl] = c1;
 		    strcpy(str + pl + 1, str2);
 		}
@@ -1791,7 +1790,7 @@
 	}
 	/* Concatenate the string before the braces (str3), the section *
 	 * just found (str4) and the text after the braces (str2)       */
-	zz = (char *)ncalloc(prev + (str - str4) + strlen(str2) + 1);
+	zz = (char *) hcalloc(prev + (str - str4) + strlen(str2) + 1);
 	ztrncpy(zz, str3, prev);
 	strncat(zz, str4, str - str4);
 	strcat(zz, str2);
@@ -1894,7 +1893,7 @@
     if (bl)
 	buf[bl - 1] = '\0';
 
-    rr = r = (char *)ncalloc(ll);
+    rr = r = (char *) hcalloc(ll);
 
     if (fl & SUB_MATCH) {
 	/* copy matched portion to new buffer */
@@ -1978,7 +1977,7 @@
  * This is called from paramsubst to get the match for ${foo#bar} etc.
  * fl is a set of the SUB_* flags defined in zsh.h
  * *sp points to the string we have to modify. The n'th match will be
- * returned in *sp. ncalloc is used to get memory for the result string.
+ * returned in *sp. The heap is used to get memory for the result string.
  * replstr is the replacement string from a ${.../orig/repl}, in
  * which case pat is the original.
  *
@@ -2009,7 +2008,7 @@
     if (!(p = compgetmatch(pat, &fl, &replstr)))
 	return;
 
-    *ap = pp = ncalloc(sizeof(char *) * (arrlen(arr) + 1));
+    *ap = pp = hcalloc(sizeof(char *) * (arrlen(arr) + 1));
     while ((*pp = *arr++))
 	if (igetmatch(pp, p, fl, n, replstr))
 	    pp++;
@@ -2022,7 +2021,6 @@
     char *s = *sp, *t, sav;
     int i, l = strlen(*sp), ml = ztrlen(*sp), matched = 1;
 
-    MUSTUSEHEAP("igetmatch");	/* presumably covered by prefork() test */
     repllist = NULL;
 
     /* perform must-match test for complex closures */
diff -ru ../z.old/Src/hist.c Src/hist.c
--- ../z.old/Src/hist.c	Wed Feb 23 14:22:03 2000
+++ Src/hist.c	Wed Feb 23 14:23:57 2000
@@ -987,9 +987,8 @@
 	    fflush(shout);
 	}
 	if (flag & HISTFLAG_RECALL) {
-	    PERMALLOC {
-		pushnode(bufstack, ptr);
-	    } LASTALLOC;
+	    zpushnode(bufstack, ptr);
+
 	    save = 0;
 	} else
 	    zsfree(ptr);
@@ -1420,7 +1419,7 @@
 	    slen += inlen - 1, sdup = 1;
     if (!sdup)
 	return out;
-    ret = pp = (char *)alloc(slen + 1);
+    ret = pp = (char *) zhalloc(slen + 1);
     for (ptr = out; *ptr; ptr++)
 	if (*ptr == '\\')
 	    *pp++ = *++ptr;
@@ -1522,7 +1521,7 @@
 	} else if (inblank(*ptr) && !inquotes && ptr[-1] != '\\')
 	    len += 2;
     ptr = *str;
-    *str = rptr = (char *)alloc(len);
+    *str = rptr = (char *) zhalloc(len);
     *rptr++ = '\'';
     for (; *ptr; ptr++)
 	if (*ptr == '\'') {
@@ -1559,7 +1558,7 @@
 	else if (inblank(*ptr))
 	    len += 2;
     ptr = *str;
-    *str = rptr = (char *)alloc(len);
+    *str = rptr = (char *) zhalloc(len);
     *rptr++ = '\'';
     for (; *ptr;)
 	if (*ptr == '\'') {
diff -ru ../z.old/Src/init.c Src/init.c
--- ../z.old/Src/init.c	Wed Feb 23 14:22:03 2000
+++ Src/init.c	Wed Feb 23 14:39:46 2000
@@ -87,13 +87,6 @@
 /**/
 mod_export sigset_t sigchld_mask;
 
-#ifdef DEBUG
-/* depth of allocation type stack */
-
-/**/
-mod_export int alloc_stackp;
-#endif
-
 /**/
 mod_export struct hookdef zshhooks[] = {
     HOOKDEF("exit", NULL, HOOKF_ALL),
@@ -106,9 +99,6 @@
 loop(int toplevel, int justonce)
 {
     Eprog prog;
-#ifdef DEBUG
-    int oasp = toplevel ? 0 : alloc_stackp;
-#endif
 
     pushheap();
     for (;;) {
@@ -138,12 +128,11 @@
 		LinkList args;
 		int osc = sfcontext;
 
-		PERMALLOC {
-		    args = newlinklist();
-		    addlinknode(args, "preexec");
-		    if (hist_ring)
-			addlinknode(args, hist_ring->text);
-		} LASTALLOC;
+		args = znewlinklist();
+		zaddlinknode(args, "preexec");
+		if (hist_ring)
+		    zaddlinknode(args, hist_ring->text);
+
 		sfcontext = SFC_HOOK;
 		doshfunc("preexec", preprog, args, 0, 1);
 		sfcontext = osc;
@@ -159,7 +148,6 @@
 	    if (toplevel)
 		noexitct = 0;
 	}
-	DPUTS(alloc_stackp != oasp, "BUG: alloc_stackp changed in loop()");
 	if (ferror(stderr)) {
 	    zerr("write error", NULL, 0);
 	    clearerr(stderr);
@@ -263,7 +251,7 @@
 	argv++;
     }
     doneoptions:
-    paramlist = newlinklist();
+    paramlist = znewlinklist();
     if (cmd) {
 	if (!*argv) {
 	    zerr("string expected after -%s", cmd, 0);
@@ -284,7 +272,7 @@
 	    argv++;
 	}
 	while (*argv)
-	    addlinknode(paramlist, ztrdup(*argv++));
+	    zaddlinknode(paramlist, ztrdup(*argv++));
     } else
 	opts[SHINSTDIN] = 1;
     if(isset(SINGLECOMMAND))
@@ -642,8 +630,8 @@
     watch    = mkarray(NULL);
     psvar    = mkarray(NULL);
     module_path = mkarray(ztrdup(MODULE_DIR));
-    modules = newlinklist();
-    linkedmodules = newlinklist();
+    modules = znewlinklist();
+    linkedmodules = znewlinklist();
 
     /* Set default prompts */
     if(unset(INTERACTIVE)) {
@@ -743,9 +731,9 @@
     trapreturn = 0;
     noerrexit = -1;
     nohistsave = 1;
-    dirstack = newlinklist();
-    bufstack = newlinklist();
-    prepromptfns = newlinklist();
+    dirstack = znewlinklist();
+    bufstack = znewlinklist();
+    prepromptfns = znewlinklist();
     hsubl = hsubr = NULL;
     lastpid = 0;
     bshin = SHIN ? fdopen(SHIN, "r") : stdin;
diff -ru ../z.old/Src/jobs.c Src/jobs.c
--- ../z.old/Src/jobs.c	Wed Feb 23 14:22:03 2000
+++ Src/jobs.c	Wed Feb 23 14:23:58 2000
@@ -565,13 +565,10 @@
     if (j->stat & STAT_TIMED)
 	return 1;
 
-    HEAPALLOC {
-	if (!(v = getvalue(&vbuf, &s, 0)) ||
-	    (reporttime = getintvalue(v)) < 0) {
-	    LASTALLOC_RETURN 0;
-	}
-    } LASTALLOC;
-
+    if (!(v = getvalue(&vbuf, &s, 0)) ||
+	(reporttime = getintvalue(v)) < 0) {
+	return 0;
+    }
     /* can this ever happen? */
     if (!j->procs)
 	return 0;
diff -ru ../z.old/Src/lex.c Src/lex.c
--- ../z.old/Src/lex.c	Wed Feb 23 14:22:03 2000
+++ Src/lex.c	Wed Feb 23 14:23:58 2000
@@ -575,7 +575,6 @@
     int c, d;
     int peekfd = -1, peek;
 
-    MUSTUSEHEAP("gettok");
   beginning:
     tokstr = NULL;
     while (iblank(c = hgetc()) && !lexstop);
@@ -587,7 +586,7 @@
     /* word includes the last character read and possibly \ before ! */
     if (dbparens) {
 	len = 0;
-	bptr = tokstr = (char *)ncalloc(bsiz = 32);
+	bptr = tokstr = (char *) hcalloc(bsiz = 32);
 	hungetc(c);
 	cmdpush(CS_MATH);
 	c = dquote_parse(infor ? ';' : ')', 0);
@@ -702,7 +701,7 @@
 	    }
 	    if (incmdpos) {
 		len = 0;
-		bptr = tokstr = (char *)ncalloc(bsiz = 32);
+		bptr = tokstr = (char *) hcalloc(bsiz = 32);
 		return cmd_or_math(CS_MATH) ? DINPAR : INPAR;
 	    }
 	} else if (d == ')')
@@ -849,7 +848,7 @@
     peek = STRING;
     if (!sub) {
 	len = 0;
-	bptr = tokstr = (char *)ncalloc(bsiz = 32);
+	bptr = tokstr = (char *) hcalloc(bsiz = 32);
     }
     for (;;) {
 	int act;
@@ -1392,28 +1391,26 @@
 {
     int l = strlen(s), err;
 
-    HEAPALLOC {
-	lexsave();
+    lexsave();
+    untokenize(s);
+    inpush(dupstring(s), 0, NULL);
+    strinbeg(0);
+    len = 0;
+    bptr = tokstr = s;
+    bsiz = l + 1;
+    err = dquote_parse('\0', 1);
+    *bptr = '\0';
+    strinend();
+    inpop();
+    DPUTS(cmdsp, "BUG: parsestr: cmdstack not empty.");
+    lexrestore();
+    if (err) {
 	untokenize(s);
-	inpush(dupstring(s), 0, NULL);
-	strinbeg(0);
-	len = 0;
-	bptr = tokstr = s;
-	bsiz = l + 1;
-	err = dquote_parse('\0', 1);
-	*bptr = '\0';
-	strinend();
-	inpop();
-	DPUTS(cmdsp, "BUG: parsestr: cmdstack not empty.");
-	lexrestore();
-	if (err) {
-	    untokenize(s);
-	    if (err > 32 && err < 127)
-		zerr("parse error near `%c'", NULL, err);
-	    else
-		zerr("parse error", NULL, 0);
-	}
-    } LASTALLOC;
+	if (err > 32 && err < 127)
+	    zerr("parse error near `%c'", NULL, err);
+	else
+	    zerr("parse error", NULL, 0);
+    }
     return err;
 }
 
diff -ru ../z.old/Src/linklist.c Src/linklist.c
--- ../z.old/Src/linklist.c	Wed Feb 23 14:22:03 2000
+++ Src/linklist.c	Wed Feb 23 14:23:58 2000
@@ -38,7 +38,19 @@
 {
     LinkList list;
 
-    list = (LinkList) ncalloc(sizeof *list);
+    list = (LinkList) zhalloc(sizeof *list);
+    list->first = NULL;
+    list->last = (LinkNode) list;
+    return list;
+}
+
+/**/
+mod_export LinkList
+znewlinklist(void)
+{
+    LinkList list;
+
+    list = (LinkList) zalloc(sizeof *list);
     list->first = NULL;
     list->last = (LinkNode) list;
     return list;
@@ -53,7 +65,25 @@
     LinkNode tmp, new;
 
     tmp = node->next;
-    node->next = new = (LinkNode) ncalloc(sizeof *tmp);
+    node->next = new = (LinkNode) zhalloc(sizeof *tmp);
+    new->last = node;
+    new->dat = dat;
+    new->next = tmp;
+    if (tmp)
+	tmp->last = new;
+    else
+	list->last = new;
+    return new;
+}
+
+/**/
+mod_export LinkNode
+zinsertlinknode(LinkList list, LinkNode node, void *dat)
+{
+    LinkNode tmp, new;
+
+    tmp = node->next;
+    node->next = new = (LinkNode) zalloc(sizeof *tmp);
     new->last = node;
     new->dat = dat;
     new->next = tmp;
@@ -226,8 +256,6 @@
 {
     LinkList list;
     LinkNode node;
-
-    MUSTUSEHEAP("newsizedlist()");
 
     list = (LinkList) zhalloc(sizeof(struct linklist) +
 			      (size * sizeof(struct linknode)));
diff -ru ../z.old/Src/loop.c Src/loop.c
--- ../z.old/Src/loop.c	Wed Feb 23 14:22:04 2000
+++ Src/loop.c	Wed Feb 23 14:23:59 2000
@@ -296,7 +296,7 @@
 
     trashzle();
     ct = countlinknodes(l);
-    ap = arr = (char **)alloc((countlinknodes(l) + 1) * sizeof(char **));
+    ap = arr = (char **) zhalloc((countlinknodes(l) + 1) * sizeof(char **));
 
     for (n = (LinkNode) firstnode(l); n; incnode(n))
 	*ap++ = (char *)getdata(n);
diff -ru ../z.old/Src/main.c Src/main.c
--- ../z.old/Src/main.c	Wed Feb 23 14:22:04 2000
+++ Src/main.c	Wed Feb 23 14:23:59 2000
@@ -39,8 +39,6 @@
     setlocale(LC_ALL, "");
 #endif
 
-    global_permalloc();
-
     init_hackzero(argv, environ);
 
     for (t = argv; *t; *t = metafy(*t, -1, META_ALLOC), t++);
@@ -79,7 +77,6 @@
     init_io();
     setupvals();
     init_signals();
-    global_heapalloc();
     init_bltinmods();
     run_init_scripts();
     init_misc();
diff -ru ../z.old/Src/math.c Src/math.c
--- ../z.old/Src/math.c	Wed Feb 23 14:22:04 2000
+++ Src/math.c	Wed Feb 23 14:23:59 2000
@@ -515,7 +515,7 @@
 	    while (*a) {
 		if (*a) {
 		    argc++;
- 		    q = (mnumber *)zhalloc(sizeof(mnumber));
+ 		    q = (mnumber *) zhalloc(sizeof(mnumber));
 		    *q = mathevall(a, ARGPREC, &a);
 		    addlinknode(l, q);
 		    if (errflag || mtok != COMMA)
@@ -864,7 +864,6 @@
     struct mathvalue *xstack = 0, nstack[STACKSZ];
     mnumber ret;
 
-    MUSTUSEHEAP("mathevall");
     if (mlevel++) {
 	xlastbase = lastbase;
 	xnoeval = noeval;
diff -ru ../z.old/Src/mem.c Src/mem.c
--- ../z.old/Src/mem.c	Wed Feb 23 14:22:04 2000
+++ Src/mem.c	Wed Feb 23 14:23:59 2000
@@ -54,9 +54,6 @@
 	Memory allocated in this way does not have to be freed explicitly;
 	it will all be freed when the pool is destroyed.  In fact,
 	attempting to free this memory may result in a core dump.
-	The pair of pointers ncalloc and alloc may point to either
-	zalloc & zcalloc or zhalloc & hcalloc; permalloc() sets them to the
-	former, and heapalloc() sets them to the latter.
 
 	If possible, the heaps are allocated using mmap() so that the
 	(*real*) heap isn't filled up with empty zsh heaps. If mmap()
@@ -81,17 +78,6 @@
 #endif
 #endif
 
-/* != 0 if we are allocating in the heaplist */
- 
-/**/
-mod_export int useheap;
-
-/* Current allocation pointers.  ncalloc() is either zalloc() or zhalloc(); *
- * alloc() is either zcalloc() or hcalloc().                               */
-
-/**/
-mod_export void *(*ncalloc) _((size_t)), *(*alloc) _((size_t));
-
 #ifdef ZSH_MEM_WARNING
 # ifndef DEBUG
 #  define DEBUG 1
@@ -115,35 +101,7 @@
 #define HEAP_ARENA_SIZE (HEAPSIZE - sizeof(struct heap))
 #define HEAPFREE (16384 - H_ISIZE)
 
-/* set default allocation to heap stack */
-
-/**/
-mod_export int
-global_heapalloc(void)
-{
-    int luh = useheap;
-
-    alloc = hcalloc;
-    ncalloc = zhalloc;
-    useheap = 1;
-    return luh;
-}
-
-/* set default allocation to malloc() */
-
-/**/
-mod_export int
-global_permalloc(void)
-{
-    int luh = useheap;
-
-    alloc = zcalloc;
-    ncalloc = zalloc;
-    useheap = 0;
-    return luh;
-}
-
-/* list of zsh heap */
+/* list of zsh heaps */
 
 static Heap heaps;
 
@@ -556,7 +514,7 @@
 
     if (!s)
 	return NULL;
-    t = (char *)ncalloc(strlen((char *)s) + 1);
+    t = (char *) zhalloc(strlen((char *)s) + 1);
     strcpy(t, s);
     return t;
 }
diff -ru ../z.old/Src/module.c Src/module.c
--- ../z.old/Src/module.c	Wed Feb 23 14:22:04 2000
+++ Src/module.c	Wed Feb 23 14:24:00 2000
@@ -77,17 +77,15 @@
 {
     Linkedmod m;
 
-    PERMALLOC {
-	m = (Linkedmod) zalloc(sizeof(*m));
+    m = (Linkedmod) zalloc(sizeof(*m));
 
-	m->name = ztrdup(n);
-	m->setup = setup;
-	m->boot = boot;
-	m->cleanup = cleanup;
-	m->finish = finish;
+    m->name = ztrdup(n);
+    m->setup = setup;
+    m->boot = boot;
+    m->cleanup = cleanup;
+    m->finish = finish;
 
-	addlinknode(linkedmodules, m);
-    } LASTALLOC;
+    zaddlinknode(linkedmodules, m);
 }
 
 /* Check if a module is linked in. */
@@ -119,9 +117,7 @@
 	return 1;
     if (bn)
 	builtintab->freenode(builtintab->removenode(builtintab, b->nam));
-    PERMALLOC {
-	builtintab->addnode(builtintab, b->nam, b);
-    } LASTALLOC;
+    builtintab->addnode(builtintab, b->nam, b);
     return 0;
 }
 
@@ -684,9 +680,8 @@
 	    m->u.linked = linked;
 	    m->flags |= MOD_SETUP | MOD_LINKED;
 	}
-	PERMALLOC {
-	    node = addlinknode(modules, m);
-	} LASTALLOC;
+	node = zaddlinknode(modules, m);
+
 	if ((set = setup_module(m)) || boot_module(m)) {
 	    if (!set)
 		finish_module(m);
@@ -796,21 +791,19 @@
     LinkNode node;
     Module m;
 
-    PERMALLOC {
-	if (!(node = find_module(name))) {
-	    m = zcalloc(sizeof(*m));
-	    m->nam = ztrdup(name);
-	    addlinknode(modules, m);
-	} else
-	    m = (Module) getdata(node);
-	if (!m->deps)
-	    m->deps = newlinklist();
-	for (node = firstnode(m->deps);
-	     node && strcmp((char *) getdata(node), from);
-	     incnode(node));
-	if (!node)
-	    addlinknode(m->deps, ztrdup(from));
-    } LASTALLOC;
+    if (!(node = find_module(name))) {
+	m = zcalloc(sizeof(*m));
+	m->nam = ztrdup(name);
+	zaddlinknode(modules, m);
+    } else
+	m = (Module) getdata(node);
+    if (!m->deps)
+	m->deps = znewlinklist();
+    for (node = firstnode(m->deps);
+	 node && strcmp((char *) getdata(node), from);
+	 incnode(node));
+    if (!node)
+	zaddlinknode(m->deps, ztrdup(from));
 }
 
 /**/
@@ -1481,9 +1474,7 @@
 
     h->next = hooktab;
     hooktab = h;
-    PERMALLOC {
-	h->funcs = newlinklist();
-    } LASTALLOC;
+    h->funcs = znewlinklist();
 
     return 0;
 }
@@ -1545,9 +1536,8 @@
 int
 addhookdeffunc(Hookdef h, Hookfn f)
 {
-    PERMALLOC {
-	addlinknode(h->funcs, (void *) f);
-    } LASTALLOC;
+    zaddlinknode(h->funcs, (void *) f);
+
     return 0;
 }
 
diff -ru ../z.old/Src/params.c Src/params.c
--- ../z.old/Src/params.c	Wed Feb 23 14:22:04 2000
+++ Src/params.c	Wed Feb 23 14:24:00 2000
@@ -408,11 +408,10 @@
 char **
 paramvalarr(HashTable ht, int flags)
 {
-    MUSTUSEHEAP("paramvalarr");
     numparamvals = 0;
     if (ht)
 	scanhashtable(ht, 0, 0, PM_UNSET, scancountparams, flags);
-    paramvals = (char **) alloc((numparamvals + 1) * sizeof(char *));
+    paramvals = (char **) zhalloc((numparamvals + 1) * sizeof(char *));
     if (ht) {
 	numparamvals = 0;
 	scanhashtable(ht, 0, 0, PM_UNSET, scanparamvals, flags);
@@ -468,87 +467,85 @@
 
     noerrs = 2;
 
-    HEAPALLOC {
-	/* Add the standard non-special parameters which have to    *
-	 * be initialized before we copy the environment variables. *
-	 * We don't want to override whatever values the users has  *
-	 * given them in the environment.                           */
-	opts[ALLEXPORT] = 0;
-	setiparam("MAILCHECK", 60);
-	setiparam("LOGCHECK", 60);
-	setiparam("KEYTIMEOUT", 40);
-	setiparam("LISTMAX", 100);
+    /* Add the standard non-special parameters which have to    *
+     * be initialized before we copy the environment variables. *
+     * We don't want to override whatever values the users has  *
+     * given them in the environment.                           */
+    opts[ALLEXPORT] = 0;
+    setiparam("MAILCHECK", 60);
+    setiparam("LOGCHECK", 60);
+    setiparam("KEYTIMEOUT", 40);
+    setiparam("LISTMAX", 100);
 #ifdef HAVE_SELECT
-	setiparam("BAUD", getbaudrate(&shttyinfo));  /* get the output baudrate */
+    setiparam("BAUD", getbaudrate(&shttyinfo));  /* get the output baudrate */
 #endif
-	setsparam("FCEDIT", ztrdup(DEFAULT_FCEDIT));
-	setsparam("TMPPREFIX", ztrdup(DEFAULT_TMPPREFIX));
-	setsparam("TIMEFMT", ztrdup(DEFAULT_TIMEFMT));
-	setsparam("WATCHFMT", ztrdup(default_watchfmt));
-	setsparam("HOST", ztrdup(hostnam));
-	setsparam("LOGNAME", ztrdup((str = getlogin()) && *str ? str : cached_username));
-
-	/* Copy the environment variables we are inheriting to dynamic *
-	 * memory, so we can do mallocs and frees on it.               */
-	num_env = arrlen(environ);
-	new_environ = (char **) zalloc(sizeof(char *) * (num_env + 1));
-	*new_environ = NULL;
-
-	/* Now incorporate environment variables we are inheriting *
-	 * into the parameter hash table.                          */
-	for (envp = new_environ, envp2 = environ; *envp2; envp2++) {
-	    for (str = *envp2; *str && *str != '='; str++);
-	    if (*str == '=') {
-		iname = NULL;
-		*str = '\0';
-		if (!idigit(**envp2) && isident(*envp2) && !strchr(*envp2, '[')) {
-		    iname = *envp2;
-		    if ((!(pm = (Param) paramtab->getnode(paramtab, iname)) ||
-			 !(pm->flags & PM_DONTIMPORT)) &&
-			(pm = setsparam(iname, metafy(str + 1, -1, META_DUP))) &&
-			!(pm->flags & PM_EXPORTED)) {
-			*str = '=';
-			pm->flags |= PM_EXPORTED;
-			pm->env = *envp++ = ztrdup(*envp2);
-			*envp = NULL;
-			if (pm->flags & PM_SPECIAL)
-			    pm->env = replenv(pm->env, getsparam(pm->nam),
-					      pm->flags);
-		    }
+    setsparam("FCEDIT", ztrdup(DEFAULT_FCEDIT));
+    setsparam("TMPPREFIX", ztrdup(DEFAULT_TMPPREFIX));
+    setsparam("TIMEFMT", ztrdup(DEFAULT_TIMEFMT));
+    setsparam("WATCHFMT", ztrdup(default_watchfmt));
+    setsparam("HOST", ztrdup(hostnam));
+    setsparam("LOGNAME", ztrdup((str = getlogin()) && *str ? str : cached_username));
+
+    /* Copy the environment variables we are inheriting to dynamic *
+     * memory, so we can do mallocs and frees on it.               */
+    num_env = arrlen(environ);
+    new_environ = (char **) zalloc(sizeof(char *) * (num_env + 1));
+    *new_environ = NULL;
+
+    /* Now incorporate environment variables we are inheriting *
+     * into the parameter hash table.                          */
+    for (envp = new_environ, envp2 = environ; *envp2; envp2++) {
+	for (str = *envp2; *str && *str != '='; str++);
+	if (*str == '=') {
+	    iname = NULL;
+	    *str = '\0';
+	    if (!idigit(**envp2) && isident(*envp2) && !strchr(*envp2, '[')) {
+		iname = *envp2;
+		if ((!(pm = (Param) paramtab->getnode(paramtab, iname)) ||
+		     !(pm->flags & PM_DONTIMPORT)) &&
+		    (pm = setsparam(iname, metafy(str + 1, -1, META_DUP))) &&
+		    !(pm->flags & PM_EXPORTED)) {
+		    *str = '=';
+		    pm->flags |= PM_EXPORTED;
+		    pm->env = *envp++ = ztrdup(*envp2);
+		    *envp = NULL;
+		    if (pm->flags & PM_SPECIAL)
+			pm->env = replenv(pm->env, getsparam(pm->nam),
+					  pm->flags);
 		}
-		*str = '=';
 	    }
+	    *str = '=';
 	}
-	environ = new_environ;
-	opts[ALLEXPORT] = oae;
+    }
+    environ = new_environ;
+    opts[ALLEXPORT] = oae;
 
-	pm = (Param) paramtab->getnode(paramtab, "HOME");
-	if (!(pm->flags & PM_EXPORTED)) {
-	    pm->flags |= PM_EXPORTED;
-	    pm->env = addenv("HOME", home, pm->flags);
-	}
-	pm = (Param) paramtab->getnode(paramtab, "LOGNAME");
-	if (!(pm->flags & PM_EXPORTED)) {
-	    pm->flags |= PM_EXPORTED;
-	    pm->env = addenv("LOGNAME", pm->u.str, pm->flags);
-	}
-	pm = (Param) paramtab->getnode(paramtab, "SHLVL");
-	if (!(pm->flags & PM_EXPORTED))
-	    pm->flags |= PM_EXPORTED;
-	sprintf(buf, "%d", (int)++shlvl);
-	pm->env = addenv("SHLVL", buf, pm->flags);
-
-	/* Add the standard non-special parameters */
-	set_pwd_env();
-	setsparam("MACHTYPE", ztrdup(MACHTYPE));
-	setsparam("OSTYPE", ztrdup(OSTYPE));
-	setsparam("TTY", ztrdup(ttystrname));
-	setsparam("VENDOR", ztrdup(VENDOR));
-	setsparam("ZSH_NAME", ztrdup(zsh_name));
-	setsparam("ZSH_VERSION", ztrdup(ZSH_VERSION));
-	setaparam("signals", sigptr = zalloc((SIGCOUNT+4) * sizeof(char *)));
-	for (t = sigs; (*sigptr++ = ztrdup(*t++)); );
-    } LASTALLOC;
+    pm = (Param) paramtab->getnode(paramtab, "HOME");
+    if (!(pm->flags & PM_EXPORTED)) {
+	pm->flags |= PM_EXPORTED;
+	pm->env = addenv("HOME", home, pm->flags);
+    }
+    pm = (Param) paramtab->getnode(paramtab, "LOGNAME");
+    if (!(pm->flags & PM_EXPORTED)) {
+	pm->flags |= PM_EXPORTED;
+	pm->env = addenv("LOGNAME", pm->u.str, pm->flags);
+    }
+    pm = (Param) paramtab->getnode(paramtab, "SHLVL");
+    if (!(pm->flags & PM_EXPORTED))
+	pm->flags |= PM_EXPORTED;
+    sprintf(buf, "%d", (int)++shlvl);
+    pm->env = addenv("SHLVL", buf, pm->flags);
+
+    /* Add the standard non-special parameters */
+    set_pwd_env();
+    setsparam("MACHTYPE", ztrdup(MACHTYPE));
+    setsparam("OSTYPE", ztrdup(OSTYPE));
+    setsparam("TTY", ztrdup(ttystrname));
+    setsparam("VENDOR", ztrdup(VENDOR));
+    setsparam("ZSH_NAME", ztrdup(zsh_name));
+    setsparam("ZSH_VERSION", ztrdup(ZSH_VERSION));
+    setaparam("signals", sigptr = zalloc((SIGCOUNT+4) * sizeof(char *)));
+    for (t = sigs; (*sigptr++ = ztrdup(*t++)); );
 
     noerrs = 0;
 }
@@ -634,7 +631,7 @@
 	if (isset(ALLEXPORT) && !oldpm)
 	    flags |= PM_EXPORTED;
     } else {
-	pm = (Param) alloc(sizeof *pm);
+	pm = (Param) zhalloc(sizeof *pm);
 	pm->nam = nulstring;
     }
     pm->flags = flags & ~PM_LOCAL;
@@ -656,29 +653,27 @@
      * to set the parameter, so must be permanently allocated (in accordance
      * with sets.?fn() usage).
      */
-    PERMALLOC {
-	tpm->flags = pm->flags;
-	if (!toplevel)
-	    tpm->flags &= ~PM_SPECIAL;
-	switch (PM_TYPE(pm->flags)) {
-	case PM_SCALAR:
-	    tpm->u.str = ztrdup(pm->gets.cfn(pm));
-	    break;
-	case PM_INTEGER:
-	    tpm->u.val = pm->gets.ifn(pm);
-	    break;
-	case PM_EFLOAT:
-	case PM_FFLOAT:
-	    tpm->u.dval = pm->gets.ffn(pm);
-	    break;
-	case PM_ARRAY:
-	    tpm->u.arr = arrdup(pm->gets.afn(pm));
-	    break;
-	case PM_HASHED:
-	    tpm->u.hash = copyparamtable(pm->gets.hfn(pm), pm->nam);
-	    break;
-	}
-    } LASTALLOC;
+    tpm->flags = pm->flags;
+    if (!toplevel)
+	tpm->flags &= ~PM_SPECIAL;
+    switch (PM_TYPE(pm->flags)) {
+    case PM_SCALAR:
+	tpm->u.str = ztrdup(pm->gets.cfn(pm));
+	break;
+    case PM_INTEGER:
+	tpm->u.val = pm->gets.ifn(pm);
+	break;
+    case PM_EFLOAT:
+    case PM_FFLOAT:
+	tpm->u.dval = pm->gets.ffn(pm);
+	break;
+    case PM_ARRAY:
+	tpm->u.arr = zarrdup(pm->gets.afn(pm));
+	break;
+    case PM_HASHED:
+	tpm->u.hash = copyparamtable(pm->gets.hfn(pm), pm->nam);
+	break;
+    }
     /*
      * If called from inside an associative array, that array is later going
      * to be passed as a real parameter, so we need the gets and sets
@@ -949,14 +944,14 @@
 	    l = strlen(s);
 	    if (a2) {
 		if (!l || *s != '*') {
-		    d = (char *) ncalloc(l + 2);
+		    d = (char *) hcalloc(l + 2);
 		    *d = '*';
 		    strcpy(d + 1, s);
 		    s = d;
 		}
 	    } else {
 		if (!l || s[l - 1] != '*') {
-		    d = (char *) ncalloc(l + 2);
+		    d = (char *) hcalloc(l + 2);
 		    strcpy(d, s);
 		    strcat(d, "*");
 		    s = d;
@@ -1010,7 +1005,7 @@
 				return r;
 		}
 	    } else if (word) {
-		ta = sepsplit(d = s = getstrvalue(v), sep, 1);
+		ta = sepsplit(d = s = getstrvalue(v), sep, 1, 1);
 		len = arrlen(ta);
 		if (beg < 0)
 		    beg += len;
@@ -1296,63 +1291,62 @@
 
     if (!v)
 	return hcalloc(1);
-    HEAPALLOC {
-	if (v->inv && !(v->pm->flags & PM_HASHED)) {
-	    sprintf(buf, "%d", v->a);
-	    s = dupstring(buf);
-	    LASTALLOC_RETURN s;
-	}
-
-	switch(PM_TYPE(v->pm->flags)) {
-	case PM_HASHED:
-	    /* (!v->isarr) should be impossible unless emulating ksh */
-	    if (!v->isarr && emulation == EMULATE_KSH) {
-		s = dupstring("[0]");
-		if (getindex(&s, v) == 0)
-		    s = getstrvalue(v);
-		LASTALLOC_RETURN s;
-	    } /* else fall through */
-	case PM_ARRAY:
-	    ss = getvaluearr(v);
-	    if (v->isarr)
-		s = sepjoin(ss, NULL);
-	    else {
-		if (v->a < 0)
-		    v->a += arrlen(ss);
-		s = (v->a >= arrlen(ss) || v->a < 0) ? (char *) hcalloc(1) : ss[v->a];
-	    }
-	    LASTALLOC_RETURN s;
-	case PM_INTEGER:
-	    convbase(buf, v->pm->gets.ifn(v->pm), v->pm->ct);
-	    s = dupstring(buf);
-	    break;
-	case PM_EFLOAT:
-	case PM_FFLOAT:
-	    s = convfloat(v->pm->gets.ffn(v->pm), v->pm->ct,
-			  v->pm->flags, NULL);
-	    break;
-	case PM_SCALAR:
-	    s = v->pm->gets.cfn(v->pm);
-	    break;
-	default:
-	    s = NULL;
-	    DPUTS(1, "BUG: param node without valid type");
-	    break;
-	}
 
-	if (v->a == 0 && v->b == -1) {
-	    LASTALLOC_RETURN s;
+    if (v->inv && !(v->pm->flags & PM_HASHED)) {
+	sprintf(buf, "%d", v->a);
+	s = dupstring(buf);
+	return s;
+    }
+
+    switch(PM_TYPE(v->pm->flags)) {
+    case PM_HASHED:
+	/* (!v->isarr) should be impossible unless emulating ksh */
+	if (!v->isarr && emulation == EMULATE_KSH) {
+	    s = dupstring("[0]");
+	    if (getindex(&s, v) == 0)
+		s = getstrvalue(v);
+	    return s;
+	} /* else fall through */
+    case PM_ARRAY:
+	ss = getvaluearr(v);
+	if (v->isarr)
+	    s = sepjoin(ss, NULL, 1);
+	else {
+	    if (v->a < 0)
+		v->a += arrlen(ss);
+	    s = (v->a >= arrlen(ss) || v->a < 0) ? (char *) hcalloc(1) : ss[v->a];
 	}
-	if (v->a < 0)
-	    v->a += strlen(s);
-	if (v->b < 0)
-	    v->b += strlen(s);
-	s = (v->a > (int)strlen(s)) ? dupstring("") : dupstring(s + v->a);
-	if (v->b < v->a)
-	    s[0] = '\0';
-	else if (v->b - v->a < (int)strlen(s))
-	    s[v->b - v->a + 1 + (s[v->b - v->a] == Meta)] = '\0';
-    } LASTALLOC;
+	return s;
+    case PM_INTEGER:
+	convbase(buf, v->pm->gets.ifn(v->pm), v->pm->ct);
+	s = dupstring(buf);
+	break;
+    case PM_EFLOAT:
+    case PM_FFLOAT:
+	s = convfloat(v->pm->gets.ffn(v->pm), v->pm->ct, v->pm->flags, NULL);
+	break;
+    case PM_SCALAR:
+	s = v->pm->gets.cfn(v->pm);
+	break;
+    default:
+	s = NULL;
+	DPUTS(1, "BUG: param node without valid type");
+	break;
+    }
+
+    if (v->a == 0 && v->b == -1)
+	return s;
+
+    if (v->a < 0)
+	v->a += strlen(s);
+    if (v->b < 0)
+	v->b += strlen(s);
+    s = (v->a > (int)strlen(s)) ? dupstring("") : dupstring(s + v->a);
+    if (v->b < v->a)
+	s[0] = '\0';
+    else if (v->b - v->a < (int)strlen(s))
+	s[v->b - v->a + 1 + (s[v->b - v->a] == Meta)] = '\0';
+
     return s;
 }
 
@@ -1386,7 +1380,7 @@
     if (v->a > arrlen(s) || v->a < 0)
 	s = arrdup(nular);
     else
-	s = arrdup(s) + v->a;
+	s = arrdup(s + v->a);
     if (v->b < v->a)
 	s[0] = NULL;
     else if (v->b - v->a < arrlen(s))
@@ -1449,7 +1443,6 @@
     v->pm->flags &= ~PM_UNSET;
     switch (PM_TYPE(v->pm->flags)) {
     case PM_SCALAR:
-	MUSTUSEHEAP("setstrvalue");
 	if (v->a == 0 && v->b == -1) {
 	    (v->pm->sets.cfn) (v->pm, val);
 	    if (v->pm->flags & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z) && !v->pm->ct)
@@ -1499,7 +1492,6 @@
 	}
 	break;
     case PM_ARRAY:
-	MUSTUSEHEAP("setstrvalue");
 	{
 	    char **ss = (char **) zalloc(2 * sizeof(char *));
 
@@ -2234,7 +2226,7 @@
 colonarrgetfn(Param pm)
 {
     char ***dptr = (char ***)pm->u.data;
-    return *dptr ? zjoin(*dptr, ':') : "";
+    return *dptr ? zjoin(*dptr, ':', 1) : "";
 }
 
 /**/
@@ -2693,7 +2685,6 @@
     int len_s;
     Param pm;
 
-    MUSTUSEHEAP("arrfixenv");
     pm = (Param) paramtab->getnode(paramtab, s);
     /*
      * Only one level of a parameter can be exported.  Unless
@@ -2703,7 +2694,7 @@
 	cmdnamtab->emptytable(cmdnamtab);
     if (isset(ALLEXPORT) ? !!pm->old : pm->level)
 	return;
-    u = t ? zjoin(t, ':') : "";
+    u = t ? zjoin(t, ':', 1) : "";
     len_s = strlen(s);
     for (ep = environ; *ep; ep++)
 	if (!strncmp(*ep, s, len_s) && (*ep)[len_s] == '=') {
@@ -2883,7 +2874,6 @@
 {
     char fmt[] = "%.*e";
 
-    MUSTUSEHEAP("convfloat");
     /*
      * The difficulty with the buffer size is that a %f conversion
      * prints all digits before the decimal point: with 64 bit doubles,
diff -ru ../z.old/Src/parse.c Src/parse.c
--- ../z.old/Src/parse.c	Wed Feb 23 14:22:04 2000
+++ Src/parse.c	Wed Feb 23 14:24:00 2000
@@ -998,7 +998,7 @@
 
 		incasepat = 1;
 		incmdpos = 0;
-		str2 = ncalloc(sl + 2);
+		str2 = hcalloc(sl + 2);
 		strcpy(str2, str);
 		str2[sl] = Bar;
 		str2[sl+1] = '\0';
@@ -1042,7 +1042,7 @@
 
 		    if (tok != STRING)
 			YYERRORV(oecused);
-		    str2 = ncalloc(sl + strlen(tokstr) + 1);
+		    str2 = hcalloc(sl + strlen(tokstr) + 1);
 		    strcpy(str2, str);
 		    strcpy(str2 + sl, tokstr);
 		    str = str2;
@@ -2008,7 +2008,7 @@
 
 /**/
 mod_export Eprog
-dupeprog(Eprog p)
+zdupeprog(Eprog p)
 {
     Eprog r;
     int i;
@@ -2017,14 +2017,15 @@
     if (p == &dummy_eprog)
 	return p;
 
-    r = (Eprog) ncalloc(sizeof(*r));
-    r->heap = useheap;
+    r = (Eprog) zalloc(sizeof(*r));
+    r->heap = 0;
     r->len = p->len;
     r->npats = p->npats;
-    pp = r->pats = (Patprog *) ncalloc(r->len);
+    pp = r->pats = (Patprog *) zcalloc(r->len);
     r->prog = (Wordcode) (r->pats + r->npats);
     r->strs = ((char *) r->prog) + (p->strs - ((char *) p->prog));
     memcpy(r->prog, p->prog, r->len - (p->npats * sizeof(Patprog)));
+    r->shf = NULL;
 
     for (i = r->npats; i--; pp++)
 	*pp = dummy_patprog1;
@@ -2038,11 +2039,8 @@
 mod_export void
 freeeprog(Eprog p)
 {
-    if (p && p != &dummy_eprog) {
-	PERMALLOC {
-	    addlinknode(eprog_free, p);
-	} LASTALLOC;
-    }
+    if (p && p != &dummy_eprog)
+	zaddlinknode(eprog_free, p);
 }
 
 /**/
@@ -2191,7 +2189,5 @@
     dummy_eprog.prog = &dummy_eprog_code;
     dummy_eprog.strs = NULL;
 
-    PERMALLOC {
-	eprog_free = newlinklist();
-    } LASTALLOC;
+    eprog_free = znewlinklist();
 }
diff -ru ../z.old/Src/pattern.c Src/pattern.c
--- ../z.old/Src/pattern.c	Wed Feb 23 14:22:04 2000
+++ Src/pattern.c	Wed Feb 23 14:24:01 2000
@@ -1357,9 +1357,7 @@
 		char *str;
 		int mlen = ztrsub(patinput, patinstart);
 
-		PERMALLOC {
-		    str = dupstrpfx(patinstart, patinput - patinstart);
-		} LASTALLOC;
+		str = ztrduppfx(patinstart, patinput - patinstart);
 		setsparam("MATCH", str);
 		setiparam("MBEGIN", (zlong)(patoffset + !isset(KSHARRAYS)));
 		setiparam("MEND",
@@ -1406,42 +1404,40 @@
 		sp = patbeginp;
 		ep = patendp;
 
-		PERMALLOC {
-		    for (i = 0; i < prog->patnpar; i++) {
-			if (parsfound & (1 << i)) {
-			    matcharr[i] = dupstrpfx(*sp, *ep - *sp);
-			    /*
-			     * mbegin and mend give indexes into the string
-			     * in the standard notation, i.e. respecting
-			     * KSHARRAYS, and with the end index giving
-			     * the last character, not one beyond.
-			     * For example, foo=foo; [[ $foo = (f)oo ]] gives
-			     * (without KSHARRAYS) indexes 1 and 1, which
-			     * corresponds to indexing as ${foo[1,1]}.
-			     */
-			    sprintf(numbuf, "%ld",
-				    (long)(ztrsub(*sp, patinstart) + 
-					   patoffset +
-					   !isset(KSHARRAYS)));
-			    mbeginarr[i] = ztrdup(numbuf);
-			    sprintf(numbuf, "%ld",
-				    (long)(ztrsub(*ep, patinstart) + 
-					   patoffset +
-					   !isset(KSHARRAYS) - 1));
-			    mendarr[i] = ztrdup(numbuf);
-			} else {
-			    /* Pattern wasn't set: either it was in an
-			     * unmatched branch, or a hashed parenthesis
-			     * that didn't match at all.
-			     */
-			    matcharr[i] = ztrdup("");
-			    mbeginarr[i] = ztrdup("-1");
-			    mendarr[i] = ztrdup("-1");
-			}
-			sp++;
-			ep++;
+		for (i = 0; i < prog->patnpar; i++) {
+		    if (parsfound & (1 << i)) {
+			matcharr[i] = ztrduppfx(*sp, *ep - *sp);
+			/*
+			 * mbegin and mend give indexes into the string
+			 * in the standard notation, i.e. respecting
+			 * KSHARRAYS, and with the end index giving
+			 * the last character, not one beyond.
+			 * For example, foo=foo; [[ $foo = (f)oo ]] gives
+			 * (without KSHARRAYS) indexes 1 and 1, which
+			 * corresponds to indexing as ${foo[1,1]}.
+			 */
+			sprintf(numbuf, "%ld",
+				(long)(ztrsub(*sp, patinstart) + 
+				       patoffset +
+				       !isset(KSHARRAYS)));
+			mbeginarr[i] = ztrdup(numbuf);
+			sprintf(numbuf, "%ld",
+				(long)(ztrsub(*ep, patinstart) + 
+				       patoffset +
+				       !isset(KSHARRAYS) - 1));
+			mendarr[i] = ztrdup(numbuf);
+		    } else {
+			/* Pattern wasn't set: either it was in an
+			 * unmatched branch, or a hashed parenthesis
+			 * that didn't match at all.
+			 */
+			matcharr[i] = ztrdup("");
+			mbeginarr[i] = ztrdup("-1");
+			mendarr[i] = ztrdup("-1");
 		    }
-		} LASTALLOC;
+		    sp++;
+		    ep++;
+		}
 		setaparam("match", matcharr);
 		setaparam("mbegin", mbeginarr);
 		setaparam("mend", mendarr);
@@ -2243,22 +2239,6 @@
 
     patinput = scan;
     return count;
-}
-
-/* Duplicate a patprog. */
-
-/**/
-Patprog
-duppatprog(Patprog prog)
-{
-    if (prog && prog != dummy_patprog1 && prog != dummy_patprog2) {
-	Patprog ret = (Patprog) alloc(prog->size);
-
-	memcpy(ret, prog, prog->size);
-
-	return ret;
-    }
-    return prog;
 }
 
 /* Free a patprog. */
diff -ru ../z.old/Src/prompt.c Src/prompt.c
--- ../z.old/Src/prompt.c	Wed Feb 23 14:22:05 2000
+++ Src/prompt.c	Wed Feb 23 14:24:01 2000
@@ -149,11 +149,10 @@
     if (isset(PROMPTSUBST)) {
 	int olderr = errflag;
 
-	HEAPALLOC {
-	    s = dupstring(s);
-	    if (!parsestr(s))
-		singsub(&s);
-	} LASTALLOC;
+	s = dupstring(s);
+	if (!parsestr(s))
+	    singsub(&s);
+
 	/* Ignore errors in prompt substitution */
 	errflag = olderr;
     }
diff -ru ../z.old/Src/signals.c Src/signals.c
--- ../z.old/Src/signals.c	Wed Feb 23 14:22:05 2000
+++ Src/signals.c	Wed Feb 23 14:24:01 2000
@@ -531,10 +531,9 @@
         if (sigtrapped[SIGALRM]) {
 	    int tmout;
             dotrap(SIGALRM);
-	    HEAPALLOC {
-		if ((tmout = getiparam("TMOUT")))
-		    alarm(tmout);           /* reset the alarm */
-	    } LASTALLOC;
+
+	    if ((tmout = getiparam("TMOUT")))
+		alarm(tmout);           /* reset the alarm */
         } else {
 	    int idle = ttyidlegetfn(NULL);
 	    int tmout = getiparam("TMOUT");
@@ -671,14 +670,12 @@
 	st->list = sigfuncs[sig];
 	sigfuncs[sig] = NULL;
     }
-    PERMALLOC {
-	if (!savetraps)
-	    savetraps = newlinklist();
-	/*
-	 * Put this at the front of the list
-	 */
-	insertlinknode(savetraps, (LinkNode)savetraps, st);
-    } LASTALLOC;
+    if (!savetraps)
+	savetraps = znewlinklist();
+    /*
+     * Put this at the front of the list
+     */
+    zinsertlinknode(savetraps, (LinkNode)savetraps, st);
 }
 
 /**/
@@ -900,23 +897,22 @@
     if (*sigtr & ZSIG_FUNC) {
 	int osc = sfcontext;
 
-	PERMALLOC {
-	    args = newlinklist();
-	    name = (char *) zalloc(5 + strlen(sigs[sig]));
-	    sprintf(name, "TRAP%s", sigs[sig]);
-	    addlinknode(args, name);
-	    sprintf(num, "%d", sig);
-	    addlinknode(args, num);
-	} LASTALLOC;
+	args = znewlinklist();
+	name = (char *) zalloc(5 + strlen(sigs[sig]));
+	sprintf(name, "TRAP%s", sigs[sig]);
+	zaddlinknode(args, name);
+	sprintf(num, "%d", sig);
+	zaddlinknode(args, num);
+
 	trapreturn = -1;
 	sfcontext = SFC_SIGNAL;
 	doshfunc(name, sigfn, args, 0, 1);
 	sfcontext = osc;
 	freelinklist(args, (FreeFunc) NULL);
 	zsfree(name);
-    } else HEAPALLOC {
+    } else
 	execode(sigfn, 1, 0);
-    } LASTALLOC;
+
     if (trapreturn > 0)
 	trapret = trapreturn;
     else if (errflag)
diff -ru ../z.old/Src/subst.c Src/subst.c
--- ../z.old/Src/subst.c	Wed Feb 23 14:22:05 2000
+++ Src/subst.c	Wed Feb 23 14:24:01 2000
@@ -51,7 +51,6 @@
 {
     LinkNode node;
 
-    MUSTUSEHEAP("prefork");
     for (node = firstnode(list); node; incnode(node)) {
 	char *str, c;
 
@@ -187,7 +186,7 @@
 	    l2 = strlen(s);
 	    if (nonempty(pl)) {
 		LinkNode n = lastnode(pl);
-		str2 = (char *) ncalloc(l1 + l2 + 1);
+		str2 = (char *) hcalloc(l1 + l2 + 1);
 		strcpy(str2, str3);
 		strcpy(str2 + l1, s);
 		setdata(node, str2);
@@ -196,7 +195,7 @@
 		l1 = 0;
 		l2 = strlen(s);
 	    }
-	    str2 = (char *) ncalloc(l1 + l2 + strlen(str) + 1);
+	    str2 = (char *) hcalloc(l1 + l2 + strlen(str) + 1);
 	    if (l1)
 		strcpy(str2, str3);
 	    strcpy(str2 + l1, s);
@@ -273,7 +272,7 @@
 	return 0;
     }
     if ((l = countlinknodes(&foo))) {
-	p = r = ncalloc((l + 1) * sizeof(char*));
+	p = r = hcalloc((l + 1) * sizeof(char*));
 	while (nonempty(&foo))
 	    *p++ = (char *)ugetnode(&foo);
 	*p = NULL;
@@ -283,7 +282,7 @@
 	    mult_isarr = omi;
 	    return 0;
 	}
-	*s = sepjoin(r, NULL);
+	*s = sepjoin(r, NULL, 1);
 	mult_isarr = omi;
 	if (isarr)
 	    *isarr = 0;
@@ -433,7 +432,7 @@
 	if (glbsub)
 	    tokenize(dest);
     } else {
-	*d = dest = ncalloc(pl + l + (s ? strlen(s) : 0) + 1);
+	*d = dest = hcalloc(pl + l + (s ? strlen(s) : 0) + 1);
 	strncpy(dest, pb, pl);
 	dest += pl;
 	strcpy(dest, src);
@@ -1041,7 +1040,7 @@
 	*s = 0;
 	if (multsub(&val, (aspar ? NULL : &aval), &isarr, NULL) && quoted) {
 	    isarr = -1;
-	    aval = alloc(sizeof(char *));
+	    aval = (char **) hcalloc(sizeof(char *));
 	    aspar = 0;
 	} else if (aspar)
 	    idbeg = val;
@@ -1167,7 +1166,7 @@
 		    else
 			while (iblank(*t))
 			    t++;
-		    val = (char *)ncalloc(fwidth + 1);
+		    val = (char *) hcalloc(fwidth + 1);
 		    val[fwidth] = '\0';
 		    if ((t0 = strlen(t)) > fwidth)
 			t0 = fwidth;
@@ -1186,7 +1185,7 @@
 				if (!*t || !idigit(*t))
 				    zero = 0;
 			    }
-			    t = (char *)ncalloc(fwidth + 1);
+			    t = (char *) hcalloc(fwidth + 1);
 			    memset(t, (((v->pm->flags & PM_RIGHT_B) || !zero) ?
 				       ' ' : '0'), fwidth);
 			    if ((t0 = strlen(val)) > fwidth)
@@ -1194,7 +1193,7 @@
 			    strcpy(t + (fwidth - t0), val);
 			    val = t;
 			} else {
-			    t = (char *)ncalloc(fwidth + 1);
+			    t = (char *) hcalloc(fwidth + 1);
 			    t[fwidth] = '\0';
 			    strncpy(t, val + strlen(val) - fwidth, fwidth);
 			    val = t;
@@ -1226,7 +1225,7 @@
 	if (nojoin)
 	    isarr = -1;
 	if (qt && !getlen && isarr > 0) {
-	    val = sepjoin(aval, sep);
+	    val = sepjoin(aval, sep, 1);
 	    isarr = 0;
 	}
     }
@@ -1376,7 +1375,7 @@
 		if (arrasg) {
 		    char *arr[2], **t, **a, **p;
 		    if (spsep || spbreak) {
-			aval = sepsplit(val, spsep, 0);
+			aval = sepsplit(val, spsep, 0, 1);
 			isarr = 2;
 			sep = spsep = NULL;
 			spbreak = 0;
@@ -1501,7 +1500,8 @@
 		else {
 		    char *ss;
 		    char **ap = aval;
-		    char **pp = aval = (char **)ncalloc(sizeof(char *) * (arrlen(aval) + 1));
+		    char **pp = aval = (char **) hcalloc(sizeof(char *) *
+							 (arrlen(aval) + 1));
 
 		    while ((*pp = *ap++)) {
 			ss = s;
@@ -1575,9 +1575,9 @@
      * It means that we must join arrays and should not split words. */
     if (ssub || spbreak || spsep || sep) {
 	if (isarr)
-	    val = sepjoin(aval, sep), isarr = 0;
+	    val = sepjoin(aval, sep, 1), isarr = 0;
 	if (!ssub && (spbreak || spsep)) {
-	    aval = sepsplit(val, spsep, 0);
+	    aval = sepsplit(val, spsep, 0, 1);
 	    if (!aval || !aval[0])
 		val = dupstring("");
 	    else if (!aval[1])
@@ -1755,7 +1755,7 @@
 	    if (aptr > (char *) getdata(n) &&
 		aptr[-1] == Dnull && *fstr == Dnull)
 		*--aptr = '\0', fstr++;
-	    y = (char *)ncalloc((aptr - ostr) + strlen(fstr) + 1);
+	    y = (char *) hcalloc((aptr - ostr) + strlen(fstr) + 1);
 	    strcpy(y, ostr);
 	    *str = y + (aptr - ostr);
 	    strcpy(*str, fstr);
@@ -1910,8 +1910,8 @@
 	b = convfloat(v.u.d, 0, 0, NULL);
     else
 	convbase(buf, v.u.l, 0);
-    t = *bptr = (char *)ncalloc(strlen(*bptr) + strlen(b) + 
-				strlen(rest) + 1);
+    t = *bptr = (char *) hcalloc(strlen(*bptr) + strlen(b) + 
+				 strlen(rest) + 1);
     t--;
     while ((*++t = *s++));
     t--;
diff -ru ../z.old/Src/utils.c Src/utils.c
--- ../z.old/Src/utils.c	Wed Feb 23 14:22:05 2000
+++ Src/utils.c	Wed Feb 23 14:24:02 2000
@@ -734,24 +734,23 @@
 
 	    if (lock) {
 		char *fn;
-		HEAPALLOC {
-		    pushheap();
-		    l = newlinklist();
-		    while ((fn = zreaddir(lock, 1)) && !errflag) {
-			if (u)
-			    sprintf(buf, "%s/%s?%s", *s, fn, u);
-			else
-			    sprintf(buf, "%s/%s", *s, fn);
-			addlinknode(l, dupstring(buf));
-			ct++;
-		    }
-		    closedir(lock);
-		    ap = arr = (char **) alloc(ct * sizeof(char *));
 
-		    while ((*ap++ = (char *)ugetnode(l)));
-		    checkmailpath(arr);
-		    popheap();
-		} LASTALLOC;
+		pushheap();
+		l = newlinklist();
+		while ((fn = zreaddir(lock, 1)) && !errflag) {
+		    if (u)
+			sprintf(buf, "%s/%s?%s", *s, fn, u);
+		    else
+			sprintf(buf, "%s/%s", *s, fn);
+		    addlinknode(l, dupstring(buf));
+		    ct++;
+		}
+		closedir(lock);
+		ap = arr = (char **) zhalloc(ct * sizeof(char *));
+
+		while ((*ap++ = (char *)ugetnode(l)));
+		checkmailpath(arr);
+		popheap();
 	    }
 	} else {
 	    if (st.st_size && st.st_atime <= st.st_mtime &&
@@ -765,15 +764,14 @@
 		    memcpy(usav, underscore, underscoreused);
 
 		    setunderscore(*s);
-		    HEAPALLOC {
-			u = dupstring(u);
-			if (! parsestr(u)) {
-			    singsub(&u);
-			    zputs(u, shout);
-			    fputc('\n', shout);
-			    fflush(shout);
-			}
-		    } LASTALLOC;
+
+		    u = dupstring(u);
+		    if (! parsestr(u)) {
+			singsub(&u);
+			zputs(u, shout);
+			fputc('\n', shout);
+			fflush(shout);
+		    }
 		    setunderscore(usav);
 		}
 	    }
@@ -1490,11 +1488,11 @@
 		if (strncmp(guess, best, preflen))
 		    return;
 		/* replace the temporarily expanded prefix with the original */
-		u = (char *) ncalloc(t - *s + strlen(best + preflen) + 1);
+		u = (char *) hcalloc(t - *s + strlen(best + preflen) + 1);
 		strncpy(u, *s, t - *s);
 		strcpy(u + (t - *s), best + preflen);
 	    } else {
-		u = (char *) ncalloc(strlen(best) + 2);
+		u = (char *) hcalloc(strlen(best) + 2);
 		strcpy(u + 1, best);
 	    }
 	    best = u;
@@ -1631,7 +1629,7 @@
 
 /**/
 mod_export char *
-zjoin(char **arr, int delim)
+zjoin(char **arr, int delim, int heap)
 {
     int len = 0;
     char **s, *ret, *ptr;
@@ -1640,7 +1638,7 @@
 	len += strlen(*s) + 1;
     if (!len)
 	return "";
-    ptr = ret = (char *) ncalloc(len);
+    ptr = ret = (heap ? (char *) hcalloc(len) : (char *) zcalloc(len));
     for (s = arr; *s; s++) {
 	strucpy(&ptr, *s);
 	if (delim)
@@ -1702,18 +1700,20 @@
 
 /**/
 mod_export char **
-spacesplit(char *s, int allownull)
+spacesplit(char *s, int allownull, int heap)
 {
     char *t, **ret, **ptr;
+    int l = sizeof(*ret) * (wordcount(s, NULL, -!allownull) + 1);
+    char *(*dup)(char *) = (heap ? dupstring : ztrdup);
 
-    ptr = ret = (char **) ncalloc(sizeof(*ret) * (wordcount(s, NULL, -!allownull) + 1));
+    ptr = ret = (heap ? (char **) hcalloc(l) : (char **) zcalloc(l));
 
     t = s;
     skipwsep(&s);
     if (*s && isep(*s == Meta ? s[1] ^ 32 : *s))
-	*ptr++ = dupstring(allownull ? "" : nulstring);
+	*ptr++ = dup(allownull ? "" : nulstring);
     else if (!allownull && t != s)
-	*ptr++ = dupstring("");
+	*ptr++ = dup("");
     while (*s) {
 	if (isep(*s == Meta ? s[1] ^ 32 : *s)) {
 	    if (*s == Meta)
@@ -1724,15 +1724,16 @@
 	t = s;
 	findsep(&s, NULL);
 	if (s > t || allownull) {
-	    *ptr = (char *) ncalloc((s - t) + 1);
+	    *ptr = (heap ? (char *) hcalloc((s - t) + 1) :
+		    (char *) zcalloc((s - t) + 1));
 	    ztrncpy(*ptr++, t, s - t);
 	} else
-	    *ptr++ = dupstring(nulstring);
+	    *ptr++ = dup(nulstring);
 	t = s;
 	skipwsep(&s);
     }
     if (!allownull && t != s)
-	*ptr++ = dupstring("");
+	*ptr++ = dup("");
     *ptr = NULL;
     return ret;
 }
@@ -1849,7 +1850,7 @@
 
 /**/
 mod_export char *
-sepjoin(char **s, char *sep)
+sepjoin(char **s, char *sep, int heap)
 {
     char *r, *p, **t;
     int l, sl;
@@ -1865,7 +1866,7 @@
     }
     sl = strlen(sep);
     for (t = s, l = 1 - sl; *t; l += strlen(*t) + sl, t++);
-    r = p = (char *) ncalloc(l);
+    r = p = (heap ? (char *) hcalloc(l) : (char *) zcalloc(l));
     t = s;
     while (*t) {
 	strucpy(&p, *t);
@@ -1878,22 +1879,24 @@
 
 /**/
 char **
-sepsplit(char *s, char *sep, int allownull)
+sepsplit(char *s, char *sep, int allownull, int heap)
 {
     int n, sl;
     char *t, *tt, **r, **p;
 
     if (!sep)
-	return spacesplit(s, allownull);
+	return spacesplit(s, allownull, heap);
 
     sl = strlen(sep);
     n = wordcount(s, sep, 1);
-    r = p = (char **) ncalloc((n + 1) * sizeof(char *));
+    r = p = (heap ? (char **) hcalloc((n + 1) * sizeof(char *)) :
+	     (char **) zcalloc((n + 1) * sizeof(char *)));
 
     for (t = s; n--;) {
 	tt = t;
 	findsep(&t, sep);
-	*p = (char *) ncalloc(t - tt + 1);
+	*p = (heap ? (char *) hcalloc(t - tt + 1) :
+	      (char *) zcalloc(t - tt + 1));
 	strncpy(*p, tt, t - tt);
 	(*p)[t - tt] = '\0';
 	p++;
@@ -2026,43 +2029,23 @@
 {
     char **x, **y;
 
-    y = x = (char **) ncalloc(sizeof(char *) * (arrlen(s) + 1));
+    y = x = (char **) zhalloc(sizeof(char *) * (arrlen(s) + 1));
 
     while ((*x++ = dupstring(*s++)));
-    return y;
-}
-
-/* Duplicate a list of strings. */
 
-/**/
-LinkList
-listdup(LinkList l)
-{
-    if (!l)
-	return NULL;
-    else {
-	LinkList r = newlinklist();
-	LinkNode n;
-
-	for (n = firstnode(l); n; incnode(n))
-	    addlinknode(r, dupstring((char *) getdata(n)));
-
-	return r;
-    }
+    return y;
 }
 
 /**/
-char **
-listarr(LinkList l)
+mod_export char **
+zarrdup(char **s)
 {
     char **x, **y;
-    LinkNode n;
 
-    x = y = (char **) ncalloc((countlinknodes(l) + 1) * sizeof(char *));
+    y = x = (char **) zalloc(sizeof(char *) * (arrlen(s) + 1));
+
+    while ((*x++ = ztrdup(*s++)));
 
-    for (n = firstnode(l); n; incnode(n))
-	*x++ = dupstring((char *) getdata(n));
-    *x = NULL;
     return y;
 }
 
@@ -2771,7 +2754,7 @@
 {
     const char *u, *tt;
     char *v;
-    char *buf = ncalloc(4 * strlen(s) + 1);
+    char *buf = hcalloc(4 * strlen(s) + 1);
     int sf = 0;
 
     tt = v = buf;
@@ -3277,7 +3260,7 @@
 mod_export char *
 dupstrpfx(const char *s, int len)
 {
-    char *r = ncalloc(len + 1);
+    char *r = zhalloc(len + 1);
 
     memcpy(r, s, len);
     r[len] = '\0';
diff -ru ../z.old/Src/zsh.h Src/zsh.h
--- ../z.old/Src/zsh.h	Wed Feb 23 14:22:06 2000
+++ Src/zsh.h	Wed Feb 23 14:24:02 2000
@@ -337,21 +337,23 @@
 
 /* Macros for manipulating link lists */
 
-#define addlinknode(X,Y) insertlinknode(X,(X)->last,Y)
-#define uaddlinknode(X,Y) uinsertlinknode(X,(X)->last,Y)
-#define empty(X)     ((X)->first == NULL)
-#define nonempty(X)  ((X)->first != NULL)
-#define firstnode(X) ((X)->first)
-#define getaddrdata(X) (&((X)->dat))
-#define getdata(X)   ((X)->dat)
-#define setdata(X,Y) ((X)->dat = (Y))
-#define lastnode(X)  ((X)->last)
-#define nextnode(X)  ((X)->next)
-#define prevnode(X)  ((X)->last)
-#define peekfirst(X) ((X)->first->dat)
-#define pushnode(X,Y) insertlinknode(X,(LinkNode) X,Y)
-#define incnode(X) (X = nextnode(X))
-#define firsthist() (hist_ring? hist_ring->down->histnum : curhist)
+#define addlinknode(X,Y)    insertlinknode(X,(X)->last,Y)
+#define zaddlinknode(X,Y)   zinsertlinknode(X,(X)->last,Y)
+#define uaddlinknode(X,Y)   uinsertlinknode(X,(X)->last,Y)
+#define empty(X)            ((X)->first == NULL)
+#define nonempty(X)         ((X)->first != NULL)
+#define firstnode(X)        ((X)->first)
+#define getaddrdata(X)      (&((X)->dat))
+#define getdata(X)          ((X)->dat)
+#define setdata(X,Y)        ((X)->dat = (Y))
+#define lastnode(X)         ((X)->last)
+#define nextnode(X)         ((X)->next)
+#define prevnode(X)         ((X)->last)
+#define peekfirst(X)        ((X)->first->dat)
+#define pushnode(X,Y)       insertlinknode(X,(LinkNode) X,Y)
+#define zpushnode(X,Y)      zinsertlinknode(X,(LinkNode) X,Y)
+#define incnode(X)          (X = nextnode(X))
+#define firsthist()         (hist_ring? hist_ring->down->histnum : curhist)
 #define setsizednode(X,Y,Z) ((X)->first[(Y)].dat = (void *) (Z))
 
 /* stack allocated linked lists */
@@ -483,7 +485,7 @@
 typedef struct eprog *Eprog;
 
 struct eprog {
-    int heap;			/* != 0 if this is in heap memory */
+    int heap;			/* != 0 if in heap memory */
     int len;			/* total block length */
     int npats;			/* Patprog cache size */
     Patprog *pats;		/* the memory block, the patterns */
@@ -1590,53 +1592,13 @@
 #endif
 ;
 
-#ifndef DEBUG
-# define HEAPALLOC	do { int nonlocal_useheap = global_heapalloc(); do
+# define LASTALLOC_RETURN return
 
-# define PERMALLOC	do { int nonlocal_useheap = global_permalloc(); do
+# define NEWHEAPS(h)    do { Heap _switch_oldheaps = h = new_heaps(); do
+# define OLDHEAPS       while (0); old_heaps(_switch_oldheaps); } while (0);
 
-# define LASTALLOC	while (0); \
-			if (nonlocal_useheap) global_heapalloc(); \
-			else global_permalloc(); \
-		} while(0)
-
-# define LASTALLOC_RETURN \
-			if ((nonlocal_useheap ? global_heapalloc() : \
-			     global_permalloc()), 0) {;} else return
-
-# define NEWHEAPS(h)    do { Heap oldheaps = h = new_heaps(); do
-# define OLDHEAPS       while (0); old_heaps(oldheaps); } while (0);
-
-# define SWITCHHEAPS(h)  do { Heap oldheaps = switch_heaps(h); do
-# define SWITCHBACKHEAPS while (0); switch_heaps(oldheaps); } while (0);
-
-#else
-# define HEAPALLOC	do { int nonlocal_useheap = global_heapalloc(); \
-			alloc_stackp++; do
-
-# define PERMALLOC	do { int nonlocal_useheap = global_permalloc(); \
-			alloc_stackp++; do
-
-# define LASTALLOC	while (0); alloc_stackp--; \
-			if (nonlocal_useheap) global_heapalloc(); \
-			else global_permalloc(); \
-		} while(0)
-
-# define LASTALLOC_RETURN \
-			if ((nonlocal_useheap ? global_heapalloc() : \
-			    global_permalloc()),alloc_stackp--,0){;}else return
-
-# define NEWHEAPS(h)    do { Heap oldheaps = h = new_heaps(); \
-                        alloc_stackp++; do
-# define OLDHEAPS       while (0); alloc_stackp--; \
-                        old_heaps(oldheaps); } while (0);
-
-# define SWITCHHEAPS(h)  do { Heap oldheaps = switch_heaps(h); \
-                         alloc_stackp++; do
-# define SWITCHBACKHEAPS while (0); alloc_stackp--; \
-                         switch_heaps(oldheaps); } while (0);
-
-#endif
+# define SWITCHHEAPS(h)  do { Heap _switch_oldheaps = switch_heaps(h); do
+# define SWITCHBACKHEAPS while (0); switch_heaps(_switch_oldheaps); } while (0);
 
 /****************/
 /* Debug macros */
@@ -1644,12 +1606,8 @@
 
 #ifdef DEBUG
 # define DPUTS(X,Y) if (!(X)) {;} else dputs(Y)
-# define MUSTUSEHEAP(X) if (useheap) {;} else \
-		fprintf(stderr, "BUG: permanent allocation in %s\n", X), \
-		fflush(stderr)
 #else
 # define DPUTS(X,Y)
-# define MUSTUSEHEAP(X)
 #endif
 
 /**************************/

--
Sven Wischnowsky                         wischnow@xxxxxxxxxxxxxxxxxxxxxxx



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