about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2003-10-28 16:52:17 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2003-10-28 16:52:17 +0000
commit40dcdf68a2368b0e889a6be5d7b6323101fcbe9f (patch)
treec0428f62747bfb85bf45a6aa2c30874b928bd235 /Src
parent0d78947de1c8480825836d76a6c6c36591e4b13e (diff)
downloadzsh-40dcdf68a2368b0e889a6be5d7b6323101fcbe9f.tar.gz
zsh-40dcdf68a2368b0e889a6be5d7b6323101fcbe9f.tar.xz
zsh-40dcdf68a2368b0e889a6be5d7b6323101fcbe9f.zip
19209: Rename zcalloc to zshcalloc.
Diffstat (limited to 'Src')
-rw-r--r--Src/Builtins/sched.c2
-rw-r--r--Src/Modules/parameter.c8
-rw-r--r--Src/Modules/stat.c39
-rw-r--r--Src/Modules/zftp.c6
-rw-r--r--Src/Zle/compcore.c12
-rw-r--r--Src/Zle/compctl.c30
-rw-r--r--Src/Zle/complete.c4
-rw-r--r--Src/Zle/computil.c2
-rw-r--r--Src/Zle/zle_keymap.c160
-rw-r--r--Src/Zle/zle_main.c160
-rw-r--r--Src/Zle/zle_refresh.c4
-rw-r--r--Src/Zle/zle_thingy.c20
-rw-r--r--Src/builtin.c8
-rw-r--r--Src/exec.c6
-rw-r--r--Src/hashtable.c14
-rw-r--r--Src/hist.c4
-rw-r--r--Src/init.c6
-rw-r--r--Src/input.c5
-rw-r--r--Src/jobs.c2
-rw-r--r--Src/mem.c102
-rw-r--r--Src/module.c413
-rw-r--r--Src/params.c6
-rw-r--r--Src/parse.c4
-rw-r--r--Src/pattern.c10
-rw-r--r--Src/prompt.c2
-rw-r--r--Src/utils.c16
26 files changed, 776 insertions, 269 deletions
diff --git a/Src/Builtins/sched.c b/Src/Builtins/sched.c
index f00a0da38..4397b84c8 100644
--- a/Src/Builtins/sched.c
+++ b/Src/Builtins/sched.c
@@ -141,7 +141,7 @@ bin_sched(char *nam, char **argv, char *ops, int func)
     }
     /* The time has been calculated; now add the new entry to the linked list
     of scheduled commands. */
-    sch = (struct schedcmd *) zcalloc(sizeof *sch);
+    sch = (struct schedcmd *) zshcalloc(sizeof *sch);
     sch->time = t;
     sch->cmd = zjoin(argv, ' ', 0);
     sch->next = NULL;
diff --git a/Src/Modules/parameter.c b/Src/Modules/parameter.c
index 6e19a377e..e023ca9fe 100644
--- a/Src/Modules/parameter.c
+++ b/Src/Modules/parameter.c
@@ -200,7 +200,7 @@ setpmcommand(Param pm, char *value)
 	zwarn("restricted: %s", value, 0);
 	zsfree(value);
     } else {
-	Cmdnam cn = zcalloc(sizeof(*cn));
+	Cmdnam cn = zshcalloc(sizeof(*cn));
 
 	cn->flags = HASHED;
 	cn->u.cmd = value;
@@ -231,7 +231,7 @@ setpmcommands(Param pm, HashTable ht)
 
     for (i = 0; i < ht->hsize; i++)
 	for (hn = ht->nodes[i]; hn; hn = hn->next) {
-	    Cmdnam cn = zcalloc(sizeof(*cn));
+	    Cmdnam cn = zshcalloc(sizeof(*cn));
 	    struct value v;
 
 	    v.isarr = v.inv = v.start = 0;
@@ -1417,7 +1417,7 @@ setpmnameddir(Param pm, char *value)
     if (!value)
 	zwarn("invalid value: ''", NULL, 0);
     else {
-	Nameddir nd = (Nameddir) zcalloc(sizeof(*nd));
+	Nameddir nd = (Nameddir) zshcalloc(sizeof(*nd));
 
 	nd->flags = 0;
 	nd->dir = value;
@@ -1466,7 +1466,7 @@ setpmnameddirs(Param pm, HashTable ht)
 	    if (!(val = getstrvalue(&v)))
 		zwarn("invalid value: ''", NULL, 0);
 	    else {
-		Nameddir nd = (Nameddir) zcalloc(sizeof(*nd));
+		Nameddir nd = (Nameddir) zshcalloc(sizeof(*nd));
 
 		nd->flags = 0;
 		nd->dir = ztrdup(val);
diff --git a/Src/Modules/stat.c b/Src/Modules/stat.c
index ab4316f7b..10f7e5c9b 100644
--- a/Src/Modules/stat.c
+++ b/Src/Modules/stat.c
@@ -35,7 +35,7 @@ enum statnum { ST_DEV, ST_INO, ST_MODE, ST_NLINK, ST_UID, ST_GID,
 		   ST_BLKSIZE, ST_BLOCKS, ST_READLINK, ST_COUNT };
 enum statflags { STF_NAME = 1,  STF_FILE = 2, STF_STRING = 4, STF_RAW = 8,
 		     STF_PICK = 16, STF_ARRAY = 32, STF_GMT = 64,
-		     STF_HASH = 128 };
+		     STF_HASH = 128, STF_OCTAL = 256 };
 static char *statelts[] = { "device", "inode", "mode", "nlink",
 				"uid", "gid", "rdev", "size", "atime",
 				"mtime", "ctime", "blksize", "blocks",
@@ -47,19 +47,40 @@ static void
 statmodeprint(mode_t mode, char *outbuf, int flags)
 {
     if (flags & STF_RAW) {
-	sprintf(outbuf, "%lu", (unsigned long)mode);
+	sprintf(outbuf, (flags & STF_OCTAL) ? "0%lo" : "%lu",
+		(unsigned long)mode);
 	if (flags & STF_STRING)
 	    strcat(outbuf, " (");
     }
     if (flags & STF_STRING) {
 	static const char *modes = "?rwxrwxrwx";
-	static const mode_t mflags[] = { S_IRUSR, S_IWUSR, S_IXUSR,
-					 S_IRGRP, S_IWGRP, S_IXGRP,
-					 S_IROTH, S_IWOTH, S_IXOTH };
+#ifdef __CYGWIN__
+	static mode_t mflags[9] = { 0 };
+#else
+	static const mode_t mflags[9] = {
+	    S_IRUSR, S_IWUSR, S_IXUSR,
+	    S_IRGRP, S_IWGRP, S_IXGRP,
+	    S_IROTH, S_IWOTH, S_IXOTH
+	};
+#endif
 	const mode_t *mfp = mflags;
 	char pm[11];
 	int i;
 
+#ifdef __CYGWIN__
+	if (mflags[0] == 0) {
+	    mflags[0] = S_IRUSR;
+	    mflags[1] = S_IWUSR;
+	    mflags[2] = S_IXUSR;
+	    mflags[3] = S_IRGRP;
+	    mflags[4] = S_IWGRP;
+	    mflags[5] = S_IXGRP;
+	    mflags[6] = S_IROTH;
+	    mflags[7] = S_IWOTH;
+	    mflags[8] = S_IXOTH;
+	}
+#endif
+
 	if (S_ISBLK(mode))
 	    *pm = 'b';
 	else if (S_ISCHR(mode))
@@ -359,7 +380,7 @@ bin_stat(char *name, char **args, char *ops, int func)
 	    flags |= STF_PICK;
 	} else {
 	    for (; *arg; arg++) {
-		if (strchr("glLnNrstT", *arg))
+		if (strchr("glLnNorstT", *arg))
 		    ops[STOUC(*arg)] = 1;
 		else if (*arg == 'A') {
 		    if (arg[1]) {
@@ -472,6 +493,8 @@ bin_stat(char *name, char **args, char *ops, int func)
 	flags |= STF_RAW;
     if (ops['n'])
 	flags |= STF_FILE;
+    if (ops['o'])
+	flags |= STF_OCTAL;
     if (ops['t'])
 	flags |= STF_NAME;
 
@@ -495,7 +518,7 @@ bin_stat(char *name, char **args, char *ops, int func)
 	arrsize = (flags & STF_PICK) ? 1 : ST_COUNT;
 	if (flags & STF_FILE)
 	    arrsize++;
-	hashptr = hash = (char **)zcalloc((arrsize+1)*2*sizeof(char *));
+	hashptr = hash = (char **)zshcalloc((arrsize+1)*2*sizeof(char *));
     }
 
     if (arrnam) {
@@ -503,7 +526,7 @@ bin_stat(char *name, char **args, char *ops, int func)
 	if (flags & STF_FILE)
 	    arrsize++;
 	arrsize *= nargs;
-	arrptr = array = (char **)zcalloc((arrsize+1)*sizeof(char *));
+	arrptr = array = (char **)zshcalloc((arrsize+1)*sizeof(char *));
     }
 
     for (; ops['f'] || *args; args++) {
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index 29ae98de5..081c6e2e2 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -2222,7 +2222,7 @@ zftp_params(char *name, char **args, int flags)
 	return 0;
     }
     len = arrlen(args);
-    newarr = (char **)zcalloc((len+1)*sizeof(char *));
+    newarr = (char **)zshcalloc((len+1)*sizeof(char *));
     for (aptr = args, i = 0; *aptr && !errflag; aptr++, i++) {
 	char *str;
 	if (**aptr == '?')
@@ -2935,10 +2935,10 @@ newsession(char *nm)
     }
 
     if (!nptr) {
-	zfsess = (Zftp_session) zcalloc(sizeof(struct zftp_session));
+	zfsess = (Zftp_session) zshcalloc(sizeof(struct zftp_session));
 	zfsess->name = ztrdup(nm);
 	zfsess->cfd = zfsess->dfd = -1;
-	zfsess->params = (char **) zcalloc(sizeof(zfparams));
+	zfsess->params = (char **) zshcalloc(sizeof(zfparams));
 	zaddlinknode(zfsessions, zfsess);
 
 	zfsesscnt++;
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 3ea9e8c4c..03e5eafc7 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -616,7 +616,7 @@ callcompfunc(char *s, char *fn)
 		untokenize(*q = ztrdup(*p));
 	    *q = NULL;
 	} else
-	    compwords = (char **) zcalloc(sizeof(char *));
+	    compwords = (char **) zshcalloc(sizeof(char *));
 
 	compparameter = ztrdup(compparameter);
 	compredirect = ztrdup(compredirect);
@@ -2706,7 +2706,7 @@ dupmatch(Cmatch m, int nbeg, int nend)
 {
     Cmatch r;
 
-    r = (Cmatch) zcalloc(sizeof(struct cmatch));
+    r = (Cmatch) zshcalloc(sizeof(struct cmatch));
 
     r->str = ztrdup(m->str);
     r->ipre = ztrdup(m->ipre);
@@ -2803,7 +2803,7 @@ permmatches(int last)
 	    if (g->mcount > 1)
 		diffmatches = 1;
 
-	    n = (Cmgroup) zcalloc(sizeof(struct cmgroup));
+	    n = (Cmgroup) zshcalloc(sizeof(struct cmgroup));
 
 	    if (g->perm) {
 		g->perm->next = NULL;
@@ -2821,7 +2821,7 @@ permmatches(int last)
 	    n->num = gn++;
 	    n->flags = g->flags;
 	    n->mcount = g->mcount;
-	    n->matches = p = (Cmatch *) zcalloc((n->mcount + 1) * sizeof(Cmatch));
+	    n->matches = p = (Cmatch *) zshcalloc((n->mcount + 1) * sizeof(Cmatch));
 	    n->name = ztrdup(g->name);
 	    for (q = g->matches; *q; q++, p++)
 		*p = dupmatch(*q, nbrbeg, nbrend);
@@ -2835,9 +2835,9 @@ permmatches(int last)
 		n->ylist = NULL;
 
 	    if ((n->ecount = g->ecount)) {
-		n->expls = ep = (Cexpl *) zcalloc((n->ecount + 1) * sizeof(Cexpl));
+		n->expls = ep = (Cexpl *) zshcalloc((n->ecount + 1) * sizeof(Cexpl));
 		for (eq = g->expls; (o = *eq); eq++, ep++) {
-		    *ep = e = (Cexpl) zcalloc(sizeof(struct cexpl));
+		    *ep = e = (Cexpl) zshcalloc(sizeof(struct cexpl));
 		    e->count = (fi ? o->fcount : o->count);
 		    e->fcount = 0;
 		    e->str = ztrdup(o->str);
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index b4981a842..d364e09d4 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -242,7 +242,7 @@ compctlread(char *name, char **args, char *ops, char *reply)
 	if (ops['A'] && !ops['e']) {
 	    /* the -A option means that one array is specified, instead of
 	    many parameters */
-	    char **p, **b = (char **)zcalloc((clwnum + 1) * sizeof(char *));
+	    char **p, **b = (char **)zshcalloc((clwnum + 1) * sizeof(char *));
 
 	    for (i = 0, p = b; i < clwnum; p++, i++)
 		*p = ztrdup(clwords[i]);
@@ -893,7 +893,7 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl)
 		    cc->xor = &cc_default;
 	    } else {
 		/* more flags follow:  prepare to loop again */
-		cc->xor = (Compctl) zcalloc(sizeof(*cc));
+		cc->xor = (Compctl) zshcalloc(sizeof(*cc));
 		cc = cc->xor;
 		memset((void *)&cct, 0, sizeof(cct));
 		cct.mask2 = CC_CCCONT;
@@ -930,7 +930,7 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
 	/* o keeps track of or's, m remembers the starting condition,
 	 * c is the current condition being parsed
 	 */
-	o = m = c = (Compcond) zcalloc(sizeof(*c));
+	o = m = c = (Compcond) zshcalloc(sizeof(*c));
 	/* Loop over each condition:  something like 's[...][...], p[...]' */
 	for (t = *argv; *t;) {
 	    while (*t == ' ')
@@ -1021,20 +1021,20 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
 	    /* Allocate space for all the arguments of the conditions */
 	    if (c->type == CCT_POS ||
 		c->type == CCT_NUMWORDS) {
-		c->u.r.a = (int *)zcalloc(n * sizeof(int));
-		c->u.r.b = (int *)zcalloc(n * sizeof(int));
+		c->u.r.a = (int *)zshcalloc(n * sizeof(int));
+		c->u.r.b = (int *)zshcalloc(n * sizeof(int));
 	    } else if (c->type == CCT_CURSUF ||
 		       c->type == CCT_CURPRE ||
 		       c->type == CCT_QUOTE)
-		c->u.s.s = (char **)zcalloc(n * sizeof(char *));
+		c->u.s.s = (char **)zshcalloc(n * sizeof(char *));
 
 	    else if (c->type == CCT_RANGESTR ||
 		     c->type == CCT_RANGEPAT) {
-		c->u.l.a = (char **)zcalloc(n * sizeof(char *));
-		c->u.l.b = (char **)zcalloc(n * sizeof(char *));
+		c->u.l.a = (char **)zshcalloc(n * sizeof(char *));
+		c->u.l.b = (char **)zshcalloc(n * sizeof(char *));
 	    } else {
-		c->u.s.p = (int *)zcalloc(n * sizeof(int));
-		c->u.s.s = (char **)zcalloc(n * sizeof(char *));
+		c->u.s.p = (int *)zshcalloc(n * sizeof(int));
+		c->u.s.s = (char **)zshcalloc(n * sizeof(char *));
 	    }
 	    /* Now loop over the actual arguments */
 	    for (l = 0; *t == '['; l++, t++) {
@@ -1137,17 +1137,17 @@ get_xcompctl(char *name, char ***av, Compctl cc, int isdef)
 		t++;
 	    if (*t == ',') {
 		/* Another condition to `or' */
-		o->or = c = (Compcond) zcalloc(sizeof(*c));
+		o->or = c = (Compcond) zshcalloc(sizeof(*c));
 		o = c;
 		t++;
 	    } else if (*t) {
 		/* Another condition to `and' */
-		c->and = (Compcond) zcalloc(sizeof(*c));
+		c->and = (Compcond) zshcalloc(sizeof(*c));
 		c = c->and;
 	    }
 	}
 	/* Assign condition to current compctl */
-	*next = (Compctl) zcalloc(sizeof(*cc));
+	*next = (Compctl) zshcalloc(sizeof(*cc));
 	(*next)->cond = m;
 	argv++;
 	/* End of the condition; get the flags that go with it. */
@@ -1271,7 +1271,7 @@ cc_reassign(Compctl cc)
      */
     Compctl c2;
 
-    c2 = (Compctl) zcalloc(sizeof *cc);
+    c2 = (Compctl) zshcalloc(sizeof *cc);
     c2->xor = cc->xor;
     c2->ext = cc->ext;
     c2->refc = 1;
@@ -1587,7 +1587,7 @@ bin_compctl(char *name, char **argv, char *ops, int func)
 	if ((ret = get_gmatcher(name, argv)))
 	    return ret - 1;
 
-	cc = (Compctl) zcalloc(sizeof(*cc));
+	cc = (Compctl) zshcalloc(sizeof(*cc));
 	if (get_compctl(name, &argv, cc, 1, 0, 0)) {
 	    freecompctl(cc);
 	    return 1;
diff --git a/Src/Zle/complete.c b/Src/Zle/complete.c
index 5f034a4a9..b9dc9f27a 100644
--- a/Src/Zle/complete.c
+++ b/Src/Zle/complete.c
@@ -686,7 +686,7 @@ restrict_range(int b, int e)
 	    e = wl;
 
 	i = e - b + 1;
-	p = (char **) zcalloc((i + 1) * sizeof(char *));
+	p = (char **) zshcalloc((i + 1) * sizeof(char *));
 
 	for (q = p, pp = compwords + b; i; i--, q++, pp++)
 	    *q = ztrdup(*pp);
@@ -1158,7 +1158,7 @@ compunsetfn(Param pm, int exp)
 		*((char **) pm->u.data) = ztrdup("");
 	    } else if (PM_TYPE(pm->flags) == PM_ARRAY) {
 		freearray(*((char ***) pm->u.data));
-		*((char ***) pm->u.data) = zcalloc(sizeof(char *));
+		*((char ***) pm->u.data) = zshcalloc(sizeof(char *));
 	    } else if (PM_TYPE(pm->flags) == PM_HASHED) {
 		deleteparamtable(pm->u.hash);
 		pm->u.hash = NULL;
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index 157a179af..500ad3163 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -124,7 +124,7 @@ cd_init(char *nam, char *sep, char **args, int disp)
     cd_state.showd = disp;
 
     while (*args) {
-	*setp = set = (Cdset) zcalloc(sizeof(*set));
+	*setp = set = (Cdset) zshcalloc(sizeof(*set));
 	setp = &(set->next);
 
 	if (!(ap = get_user_var(*args))) {
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index 28203655e..9ac6dc8ed 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -86,6 +86,16 @@ struct bindstate {
     char *lastseq;
     Thingy bind;
     char *str;
+    char *prefix;
+    int prefixlen;
+};
+
+/* This structure is used when scanning for prefix bindings to remove */
+
+struct remprefstate {
+    Keymap km;
+    char *prefix;
+    int prefixlen;
 };
 
 #define BS_LIST (1<<0)
@@ -146,7 +156,7 @@ createkeymapnamtab(void)
 static KeymapName
 makekeymapnamnode(Keymap keymap)
 {
-    KeymapName kmn = (KeymapName) zcalloc(sizeof(*kmn));
+    KeymapName kmn = (KeymapName) zshcalloc(sizeof(*kmn));
 
     kmn->keymap = keymap;
     return kmn;
@@ -191,7 +201,7 @@ newkeytab(char *kmname)
 static Key
 makekeynode(Thingy t, char *str)
 {
-    Key k = (Key) zcalloc(sizeof(*k));
+    Key k = (Key) zshcalloc(sizeof(*k));
 
     k->bind = t;
     k->str = str;
@@ -220,7 +230,7 @@ static HashTable copyto;
 mod_export Keymap
 newkeymap(Keymap tocopy, char *kmname)
 {
-    Keymap km = zcalloc(sizeof(*km));
+    Keymap km = zshcalloc(sizeof(*km));
     int i;
 
     km->rc = 0;
@@ -834,6 +844,19 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
 	zwarnnam(name, "keymap `%s' is protected", kmname, 0);
 	return 1;
     }
+    if (func == 'r' && ops['p']) {
+	char *useq, *bseq;
+	int len;
+	struct remprefstate rps;
+	rps.km = km;
+	while ((useq = *argv++)) {
+	    bseq = getkeystring(useq, &len, 2, NULL);
+	    rps.prefix = metafy(bseq, len, META_USEHEAP);
+	    rps.prefixlen = strlen(rps.prefix);
+	    scankeymap(km, 0, scanremoveprefix, &rps);
+	}
+	return 0;
+    }
     do {
 	char *useq = *argv, *bseq, *seq, *str;
 	int len;
@@ -878,6 +901,20 @@ bin_bindkey_bind(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
     return ret;
 }
 
+/* Remove bindings for key sequences which have the given (proper) prefix. */
+
+/**/
+static void
+scanremoveprefix(char *seq, Thingy bind, char *str, void *magic)
+{
+    struct remprefstate *rps = magic;
+
+    if (strncmp(seq, rps->prefix, rps->prefixlen) || !seq[rps->prefixlen])
+	return;
+
+    bindkey(rps->km, seq, refthingy(t_undefinedkey), NULL);
+}
+
 /* List key bindings.  If an argument is given, list just that one *
  * binding, otherwise list the entire keymap.  If the -L option is *
  * given, list in the form of bindkey commands.                    */
@@ -890,7 +927,7 @@ bin_bindkey_list(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
 
     bs.flags = ops['L'] ? BS_LIST : 0;
     bs.kmname = kmname;
-    if(argv[0]) {
+    if(argv[0] && !ops['p']) {
 	int len;
 	char *seq;
 
@@ -899,8 +936,23 @@ bin_bindkey_list(char *name, char *kmname, Keymap km, char **argv, char *ops, ch
 	bs.flags |= BS_ALL;
 	bs.firstseq = bs.lastseq = seq;
 	bs.bind = keybind(km, seq, &bs.str);
+	bs.prefix = NULL;
+	bs.prefixlen = 0;
 	bindlistout(&bs);
     } else {
+	/* empty prefix is equivalent to no prefix */
+	if (ops['p'] && (!argv[0] || argv[0][0])) {
+	    if (!argv[0]) {
+		zwarnnam(name, "option -p requires a prefix string", NULL, 0);
+		return 1;
+	    }
+	    bs.prefix = getkeystring(argv[0], &bs.prefixlen, 2, NULL);
+	    bs.prefix = metafy(bs.prefix, bs.prefixlen, META_HREALLOC);
+	    bs.prefixlen = strlen(bs.prefix);
+	} else {
+	    bs.prefix = NULL;
+	    bs.prefixlen = 0;
+	}
 	bs.firstseq = ztrdup("");
 	bs.lastseq = ztrdup("");
 	bs.bind = t_undefinedkey;
@@ -919,6 +971,10 @@ scanbindlist(char *seq, Thingy bind, char *str, void *magic)
 {
     struct bindstate *bs = magic;
 
+    if (bs->prefixlen &&
+	(strncmp(seq, bs->prefix, bs->prefixlen) || !seq[bs->prefixlen]))
+	return;
+
     if(bind == bs->bind && (bind || !strcmp(str, bs->str)) &&
        ztrlen(seq) == 1 && ztrlen(bs->lastseq) == 1) {
 	int l = bs->lastseq[1] ?
@@ -1011,6 +1067,66 @@ cleanup_keymaps(void)
     zfree(keybuf, keybufsz);
 }
 
+static char *cursorptr;
+
+/* utility function for termcap output routine to add to string */
+
+static int 
+add_cursor_char(int c)
+{
+    *cursorptr++ = c;
+    return 0;
+}
+
+/* interrogate termcap for cursor keys and add bindings to keymap */
+
+/**/
+static void
+add_cursor_key(Keymap km, int tccode, Thingy thingy, int defchar)
+{
+    char buf[2048];
+    int ok = 0;
+
+    /*
+     * Be careful not to try too hard with bindings for dubious or
+     * dysfunctional terminals.
+     */
+    if (tccan(tccode) && !(termflags & (TERM_NOUP|TERM_BAD|TERM_UNKNOWN))) {
+	/*
+	 * We can use the real termcap sequence.  We need to
+	 * persuade termcap to output `move cursor 1 char' and capture it.
+	 */
+	cursorptr = buf;
+	tputs(tcstr[tccode], 1, add_cursor_char);
+	*cursorptr = '\0';
+
+	/*
+	 * Sanity checking.  If the cursor key is zero-length (unlikely,
+	 * but this is termcap we're talking about), or it's a single
+	 * character, then we don't bind it.
+	 */
+	if (buf[0] && buf[1] && (buf[0] != Meta || buf[2]))
+	    ok = 1;
+    }
+    if (!ok) {
+	/* Assume the normal VT100-like values. */
+	sprintf(buf, "\33[%c", defchar);
+    }
+    bindkey(km, buf, refthingy(thingy), NULL);
+
+    /*
+     * If the string looked like \e[? or \eO?, bind the other one, too.
+     * This is necessary to make cursor keys work on many xterms with
+     * both normal and application modes.
+     */
+    if (buf[0] == '\33' && (buf[1] == '[' || buf[1] == 'O') && 
+	buf[2] && !buf[3])
+    {
+	buf[1] = (buf[1] == '[') ? 'O' : '[';
+	bindkey(km, buf, refthingy(thingy), NULL);
+    }
+}
+
 /* Create the default keymaps.  For efficiency reasons, this function   *
  * assigns directly to the km->first array.  It knows that there are no *
  * prefix bindings in the way, and that it is using a simple keymap.    */
@@ -1023,6 +1139,7 @@ default_bindings(void)
     Keymap emap = newkeymap(NULL, "emacs");
     Keymap amap = newkeymap(NULL, "vicmd");
     Keymap smap = newkeymap(NULL, ".safe");
+    Keymap vimaps[2], kptr;
     char buf[3], *ed;
     int i;
 
@@ -1066,25 +1183,22 @@ default_bindings(void)
     /* vt100 arrow keys are bound by default, for historical reasons. *
      * Both standard and keypad modes are supported.                  */
 
-    /* vi command mode: arrow keys */
-    bindkey(amap, "\33[A",  refthingy(t_uplineorhistory), NULL);
-    bindkey(amap, "\33[B",  refthingy(t_downlineorhistory), NULL);
-    bindkey(amap, "\33[C",  refthingy(t_viforwardchar), NULL);
-    bindkey(amap, "\33[D",  refthingy(t_vibackwardchar), NULL);
-    bindkey(amap, "\33OA",  refthingy(t_uplineorhistory), NULL);
-    bindkey(amap, "\33OB",  refthingy(t_downlineorhistory), NULL);
-    bindkey(amap, "\33OC",  refthingy(t_viforwardchar), NULL);
-    bindkey(amap, "\33OD",  refthingy(t_vibackwardchar), NULL);
-
-    /* emacs mode: arrow keys */
-    bindkey(emap, "\33[A",  refthingy(t_uplineorhistory), NULL);
-    bindkey(emap, "\33[B",  refthingy(t_downlineorhistory), NULL);
-    bindkey(emap, "\33[C",  refthingy(t_forwardchar), NULL);
-    bindkey(emap, "\33[D",  refthingy(t_backwardchar), NULL);
-    bindkey(emap, "\33OA",  refthingy(t_uplineorhistory), NULL);
-    bindkey(emap, "\33OB",  refthingy(t_downlineorhistory), NULL);
-    bindkey(emap, "\33OC",  refthingy(t_forwardchar), NULL);
-    bindkey(emap, "\33OD",  refthingy(t_backwardchar), NULL);
+    vimaps[0] = vmap;
+    vimaps[1] = amap;
+    for (i = 0; i < 2; i++) {
+	kptr = vimaps[i];
+	/* vi command and insert modes: arrow keys */
+	add_cursor_key(kptr, TCUPCURSOR, t_uplineorhistory, 'A');
+	add_cursor_key(kptr, TCDOWNCURSOR, t_downlineorhistory, 'B');
+	add_cursor_key(kptr, TCLEFTCURSOR, t_vibackwardchar, 'D');
+	add_cursor_key(kptr, TCRIGHTCURSOR, t_viforwardchar, 'C');
+    }
+
+    /* emacs mode: arrow keys */ 
+    add_cursor_key(emap, TCUPCURSOR, t_uplineorhistory, 'A');
+    add_cursor_key(emap, TCDOWNCURSOR, t_downlineorhistory, 'B');
+    add_cursor_key(emap, TCLEFTCURSOR, t_backwardchar, 'D');
+    add_cursor_key(emap, TCRIGHTCURSOR, t_forwardchar, 'C');
    
     /* emacs mode: ^X sequences */
     bindkey(emap, "\30*",   refthingy(t_expandword), NULL);
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index aa5086597..6156b40d0 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -76,7 +76,10 @@ mod_export Thingy lbindk, bindk;
 /**/
 int insmode;
 
-static int eofchar, eofsent;
+/**/
+mod_export int eofchar;
+
+static int eofsent;
 static long keytimeout;
 
 #ifdef HAVE_SELECT
@@ -313,6 +316,7 @@ breakread(int fd, char *buf, int n)
 
     FD_ZERO(&f);
     FD_SET(fd, &f);
+
     return (select(fd + 1, (SELECT_ARG_2_T) & f, NULL, NULL, NULL) == -1 ?
 	    EOF : read(fd, buf, n));
 }
@@ -395,7 +399,13 @@ getkey(int keytmout)
 # endif
 #endif
 	}
-	while ((r = read(SHTTY, &cc, 1)) != 1) {
+	for (;;) {
+	    int q = queue_signal_level();
+	    dont_queue_signals();
+	    r = read(SHTTY, &cc, 1);
+	    restore_queue_signals(q);
+	    if (r == 1)
+		break;
 	    if (r == 0) {
 		/* The test for IGNOREEOF was added to make zsh ignore ^Ds
 		   that were typed while commands are running.  Unfortuantely
@@ -556,7 +566,7 @@ zleread(char *lp, char *rp, int flags)
 	reselectkeymap();
 	selectlocalmap(NULL);
 	bindk = getkeycmd();
-	if (!ll && isfirstln && c == eofchar) {
+	if (!ll && isfirstln && unset(IGNOREEOF) && c == eofchar) {
 	    eofsent = 1;
 	    break;
 	}
@@ -630,23 +640,36 @@ execzlefunc(Thingy func, char **args)
     } else if((w = func->widget)->flags & (WIDGET_INT|WIDGET_NCOMP)) {
 	int wflags = w->flags;
 
-	if(!(wflags & ZLE_KEEPSUFFIX))
-	    removesuffix();
-	if(!(wflags & ZLE_MENUCMP)) {
-	    fixsuffix();
-	    invalidatelist();
+	if (keybuf[0] == eofchar && !keybuf[1] &&
+	    !ll && isfirstln && isset(IGNOREEOF)) {
+	    showmsg((!islogin) ? "zsh: use 'exit' to exit." :
+		    "zsh: use 'logout' to logout.");
+	    ret = 1;
+	} else {
+	    if(!(wflags & ZLE_KEEPSUFFIX))
+		removesuffix();
+	    if(!(wflags & ZLE_MENUCMP)) {
+		fixsuffix();
+		invalidatelist();
+	    }
+	    if (wflags & ZLE_LINEMOVE)
+		vilinerange = 1;
+	    if(!(wflags & ZLE_LASTCOL))
+		lastcol = -1;
+	    if (wflags & WIDGET_NCOMP) {
+		int atcurhist = histline == curhist;
+		compwidget = w;
+		ret = completecall(args);
+		if (atcurhist)
+		    histline = curhist;
+	    } else {
+		queue_signals();
+		ret = w->u.fn(args);
+		unqueue_signals();
+	    }
+	    if (!(wflags & ZLE_NOTCOMMAND))
+		lastcmd = wflags;
 	}
-	if (wflags & ZLE_LINEMOVE)
-	    vilinerange = 1;
-	if(!(wflags & ZLE_LASTCOL))
-	    lastcol = -1;
-	if (wflags & WIDGET_NCOMP) {
-	    compwidget = w;
-	    ret = completecall(args);
-	} else
-	    ret = w->u.fn(args);
-	if (!(wflags & ZLE_NOTCOMMAND))
-	    lastcmd = wflags;
 	r = 1;
     } else {
 	Eprog prog = getshfunc(w->u.fnnam);
@@ -735,11 +758,15 @@ bin_vared(char *name, char **args, char *ops, int func)
     struct value vbuf;
     Value v;
     Param pm = 0;
-    int create = 0, ifl;
+    int create = 0, ifl, ieof;
     int type = PM_SCALAR, obreaks = breaks, haso = 0;
     char *p1 = NULL, *p2 = NULL;
     FILE *oshout = NULL;
 
+    if ((interact && unset(USEZLE)) || !strcmp(term, "emacs")) {
+	zwarnnam(name, "ZLE not enabled", NULL, 0);
+	return 1;
+    }
     if (zleactive) {
 	zwarnnam(name, "ZLE cannot be used recursively (yet)", NULL, 0);
 	return 1;
@@ -810,17 +837,65 @@ bin_vared(char *name, char **args, char *ops, int func)
     }
     /* handle non-existent parameter */
     s = args[0];
+    queue_signals();
     v = fetchvalue(&vbuf, &s, (!create || type == PM_SCALAR),
 		   SCANPM_WANTKEYS|SCANPM_WANTVALS|SCANPM_MATCHMANY);
     if (!v && !create) {
+	unqueue_signals();
 	zwarnnam(name, "no such variable: %s", args[0], 0);
 	return 1;
     } else if (v) {
-	s = getstrvalue(v);
-	pm = v->pm;
+	if (v->isarr) {
+	    /* Array: check for separators and quote them. */
+	    char **arr = getarrvalue(v), **aptr, **tmparr, **tptr;
+	    tptr = tmparr = (char **)zhalloc(sizeof(char *)*(arrlen(arr)+1));
+	    for (aptr = arr; *aptr; aptr++) {
+		int sepcount = 0;
+		/*
+		 * See if this word contains a separator character
+		 * or backslash
+		 */
+		for (t = *aptr; *t; t++) {
+		    if (*t == Meta) {
+			if (isep(t[1] ^ 32))
+			    sepcount++;
+			t++;
+		    } else if (isep(*t) || *t == '\\')
+			sepcount++;
+		}
+		if (sepcount) {
+		    /* Yes, so allocate enough space to quote it. */
+		    char *newstr, *nptr;
+		    newstr = zhalloc(strlen(*aptr)+sepcount+1);
+		    /* Go through string quoting separators */
+		    for (t = *aptr, nptr = newstr; *t; ) {
+			if (*t == Meta) {
+			    if (isep(t[1] ^ 32))
+				*nptr++ = '\\';
+			    *nptr++ = *t++;
+			} else if (isep(*t) || *t == '\\')
+			    *nptr++ = '\\';
+			*nptr++ = *t++;
+		    }
+		    *nptr = '\0';
+		    /* Stick this into the array of words to join up */
+		    *tptr++ = newstr;
+		} else
+		    *tptr++ = *aptr; /* No, keep original array element */
+	    }
+	    *tptr = NULL;
+	    s = sepjoin(tmparr, NULL, 0);
+	} else {
+	    s = ztrdup(getstrvalue(v));
+	}
+	unqueue_signals();
     } else if (*s) {
+	unqueue_signals();
 	zwarnnam(name, "invalid parameter name: %s", args[0], 0);
 	return 1;
+    } else {
+	unqueue_signals();
+	s = ztrdup(s);
     }
 
     if (SHTTY == -1) {
@@ -835,22 +910,23 @@ bin_vared(char *name, char **args, char *ops, int func)
 	haso = 1;
     }
     /* edit the parameter value */
-    zpushnode(bufstack, ztrdup(s));
+    zpushnode(bufstack, s);
 
     varedarg = *args;
     ifl = isfirstln;
-    if (ops['e'])
-	isfirstln = 1;
     if (ops['h'])
-	hbegin(1);
+	hbegin(2);
+    isfirstln = ops['e'];
+    ieof = opts[IGNOREEOF];
+    opts[IGNOREEOF] = 0;
     t = (char *) zleread(p1, p2, ops['h'] ? ZLRF_HISTORY : 0);
+    opts[IGNOREEOF] = ieof;
     if (ops['h'])
-	hend();
+	hend(NULL);
     isfirstln = ifl;
     varedarg = ova;
     if (haso) {
-	close(SHTTY);
-	fclose(shout);
+	fclose(shout);	/* close(SHTTY) */
 	shout = oshout;
 	SHTTY = -1;
     }
@@ -864,24 +940,27 @@ bin_vared(char *name, char **args, char *ops, int func)
     if (t[strlen(t) - 1] == '\n')
 	t[strlen(t) - 1] = '\0';
     /* final assignment of parameter value */
-    if (create && (!pm || (type && PM_TYPE(pm->flags) != type))) {
-	if (pm)
-	    unsetparam(args[0]);
+    if (create) {
+	unsetparam(args[0]);
 	createparam(args[0], type);
-	pm = 0;
     }
-    if (!pm)
-	pm = (Param) paramtab->getnode(paramtab, args[0]);
+    queue_signals();
+    pm = (Param) paramtab->getnode(paramtab, args[0]);
     if (pm && (PM_TYPE(pm->flags) & (PM_ARRAY|PM_HASHED))) {
 	char **a;
 
-	a = spacesplit(t, 1, 0);
+	/*
+	 * Use spacesplit with fourth argument 1: identify quoted separators,
+	 * unquote but don't split.
+	 */
+	a = spacesplit(t, 1, 0, 1);
 	if (PM_TYPE(pm->flags) == PM_ARRAY)
 	    setaparam(args[0], a);
 	else
 	    sethparam(args[0], a);
     } else
 	setsparam(args[0], t);
+    unqueue_signals();
     return 0;
 }
 
@@ -1015,9 +1094,9 @@ zleaftertrap(Hookdef dummy, void *dat)
 }
 
 static struct builtin bintab[] = {
-    BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLR", NULL),
+    BUILTIN("bindkey", 0, bin_bindkey, 0, -1, 0, "evaMldDANmrsLRp", NULL),
     BUILTIN("vared",   0, bin_vared,   1,  7, 0, NULL,             NULL),
-    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "lDANCLmMgGcRaU", NULL),
+    BUILTIN("zle",     0, bin_zle,     0, -1, 0, "lDANCLmMgGcRaUI", NULL),
 };
 
 /* The order of the entries in this table has to match the *HOOK
@@ -1040,7 +1119,6 @@ setup_(Module m)
 {
     /* Set up editor entry points */
     trashzleptr = trashzle;
-    gotwordptr = gotword;
     refreshptr = zrefresh;
     spaceinlineptr = spaceinline;
     zlereadptr = zleread;
@@ -1054,6 +1132,7 @@ setup_(Module m)
     /* miscellaneous initialisations */
     stackhist = stackcs = -1;
     kungetbuf = (char *) zalloc(kungetsz = 32);
+    comprecursive = 0;
 
     /* initialise the keymap system */
     init_keymaps();
@@ -1062,7 +1141,7 @@ setup_(Module m)
 
     incompfunc = incompctlfunc = hascompmod = 0;
 
-    clwords = (char **) zcalloc((clwsize = 16) * sizeof(char *));
+    clwords = (char **) zshcalloc((clwsize = 16) * sizeof(char *));
 
     return 0;
 }
@@ -1117,7 +1196,6 @@ finish_(Module m)
 
     /* editor entry points */
     trashzleptr = noop_function;
-    gotwordptr = noop_function;
     refreshptr = noop_function;
     spaceinlineptr = noop_function_int;
     zlereadptr = fallback_zleread;
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index c432907d1..68860f391 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -133,8 +133,8 @@ resetvideo(void)
 	    free(nbuf);
 	    free(obuf);
 	}
-	nbuf = (char **)zcalloc((winh + 1) * sizeof(char *));
-	obuf = (char **)zcalloc((winh + 1) * sizeof(char *));
+	nbuf = (char **)zshcalloc((winh + 1) * sizeof(char *));
+	obuf = (char **)zshcalloc((winh + 1) * sizeof(char *));
 	nbuf[0] = (char *)zalloc(winw + 2);
 	obuf[0] = (char *)zalloc(winw + 2);
 
diff --git a/Src/Zle/zle_thingy.c b/Src/Zle/zle_thingy.c
index 1d1eaacf3..f40bd18b8 100644
--- a/Src/Zle/zle_thingy.c
+++ b/Src/Zle/zle_thingy.c
@@ -107,7 +107,7 @@ scanemptythingies(HashNode hn, int flags)
 static Thingy
 makethingynode(void)
 {
-    Thingy t = (Thingy) zcalloc(sizeof(*t));
+    Thingy t = (Thingy) zshcalloc(sizeof(*t));
 
     t->flags = DISABLED;
     return t;
@@ -339,6 +339,7 @@ bin_zle(char *name, char **args, char *ops, int func)
 	{ 'R', bin_zle_refresh, 0, -1 },
 	{ 'M', bin_zle_mesg, 1, 1 },
 	{ 'U', bin_zle_unget, 1, 1 },
+	{ 'I', bin_zle_invalidate, 0, 0 },
 	{ 0,   bin_zle_call, 0, -1 },
     };
     struct opn const *op, *opp;
@@ -396,10 +397,8 @@ bin_zle_refresh(char *name, char **args, char *ops, char func)
     char *s = statusline;
     int sl = statusll, ocl = clearlist;
 
-    if (!zleactive) {
-	zwarnnam(name, "can only be called from widget function", NULL, 0);
+    if (!zleactive)
 	return 1;
-    }
     statusline = NULL;
     statusll = 0;
     if (*args) {
@@ -628,7 +627,7 @@ bin_zle_call(char *name, char **args, char *ops, char func)
 		    return 1;
 		}
 		if (!args[0][1])
-		    args++;
+		    *++args = "" - 1;
 		modsave = zmod;
 		saveflag = 1;
 		zmod.mult = atoi(num);
@@ -656,6 +655,17 @@ bin_zle_call(char *name, char **args, char *ops, char func)
     return ret;
 }
 
+/**/
+static int
+bin_zle_invalidate(char *name, char **args, char *ops, char func)
+{
+    if (zleactive) {
+	trashzle();
+	return 0;
+    } else
+	return 1;
+}
+
 /*******************/
 /* initialiasation */
 /*******************/
diff --git a/Src/builtin.c b/Src/builtin.c
index c1468c6aa..bfb2f85b8 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -2207,7 +2207,7 @@ bin_functions(char *name, char **argv, char *ops, int func)
 		DPUTS(!shf->funcdef,
 		      "BUG: Calling autoload from empty function");
 	    } else {
-		shf = (Shfunc) zcalloc(sizeof *shf);
+		shf = (Shfunc) zshcalloc(sizeof *shf);
 		shfunctab->addnode(shfunctab, ztrdup(scriptname), shf);
 	    }
 	    shf->flags = on;
@@ -2278,7 +2278,7 @@ bin_functions(char *name, char **argv, char *ops, int func)
 	} else if (on & PM_UNDEFINED) {
 	    /* Add a new undefined (autoloaded) function to the *
 	     * hash table with the corresponding flags set.     */
-	    shf = (Shfunc) zcalloc(sizeof *shf);
+	    shf = (Shfunc) zshcalloc(sizeof *shf);
 	    shf->flags = on;
 	    shf->funcdef = mkautofn(shf);
 	    shfunctab->addnode(shfunctab, ztrdup(*argv), shf);
@@ -2665,11 +2665,11 @@ bin_hash(char *name, char **argv, char *ops, int func)
 		/* The argument is of the form foo=bar, *
 		 * so define an entry for the table.    */
 		if(ops['d']) {
-		    Nameddir nd = hn = zcalloc(sizeof *nd);
+		    Nameddir nd = hn = zshcalloc(sizeof *nd);
 		    nd->flags = 0;
 		    nd->dir = ztrdup(asg->value);
 		} else {
-		    Cmdnam cn = hn = zcalloc(sizeof *cn);
+		    Cmdnam cn = hn = zshcalloc(sizeof *cn);
 		    cn->flags = HASHED;
 		    cn->u.cmd = ztrdup(asg->value);
 		}
diff --git a/Src/exec.c b/Src/exec.c
index fec58c511..81c6ac641 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -688,7 +688,7 @@ hashcmd(char *arg0, char **pp)
     if (!*pp)
 	return NULL;
 
-    cn = (Cmdnam) zcalloc(sizeof *cn);
+    cn = (Cmdnam) zshcalloc(sizeof *cn);
     cn->flags = 0;
     cn->u.name = pp;
     cmdnamtab->addnode(cmdnamtab, ztrdup(arg0), cn);
@@ -3358,7 +3358,7 @@ doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval)
 	LinkNode node;
 
 	node = doshargs->first;
-	pparams = x = (char **) zcalloc(((sizeof *x) *
+	pparams = x = (char **) zshcalloc(((sizeof *x) *
 					 (1 + countlinknodes(doshargs))));
 	if (isset(FUNCTIONARGZERO)) {
 	    oargv0 = argzero;
@@ -3368,7 +3368,7 @@ doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval)
 	for (; node; node = node->next, x++)
 	    *x = ztrdup((char *) node->dat);
     } else {
-	pparams = (char **) zcalloc(sizeof *pparams);
+	pparams = (char **) zshcalloc(sizeof *pparams);
 	if (isset(FUNCTIONARGZERO)) {
 	    oargv0 = argzero;
 	    argzero = ztrdup(argzero);
diff --git a/Src/hashtable.c b/Src/hashtable.c
index 332f9479a..5c93bd0c1 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -96,7 +96,7 @@ newhashtable(int size, char const *name, PrintTableStats printinfo)
 {
     HashTable ht;
 
-    ht = (HashTable) zcalloc(sizeof *ht);
+    ht = (HashTable) zshcalloc(sizeof *ht);
 #ifdef ZSH_HASH_DEBUG
     ht->next = NULL;
     if(!firstht)
@@ -108,7 +108,7 @@ newhashtable(int size, char const *name, PrintTableStats printinfo)
     ht->printinfo = printinfo ? printinfo : printhashtabinfo;
     ht->tablename = ztrdup(name);
 #endif /* ZSH_HASH_DEBUG */
-    ht->nodes = (HashNode *) zcalloc(size * sizeof(HashNode));
+    ht->nodes = (HashNode *) zshcalloc(size * sizeof(HashNode));
     ht->hsize = size;
     ht->ct = 0;
     ht->scan = NULL;
@@ -458,7 +458,7 @@ expandhashtable(HashTable ht)
     onodes = ht->nodes;
 
     ht->hsize = osize * 4;
-    ht->nodes = (HashNode *) zcalloc(ht->hsize * sizeof(HashNode));
+    ht->nodes = (HashNode *) zshcalloc(ht->hsize * sizeof(HashNode));
     ht->ct = 0;
 
     /* scan through the old list of nodes, and *
@@ -496,7 +496,7 @@ resizehashtable(HashTable ht, int newsize)
      * we free it and allocate a new nodes array.          */
     if (ht->hsize != newsize) {
 	zfree(ht->nodes, ht->hsize * sizeof(HashNode));
-	ht->nodes = (HashNode *) zcalloc(newsize * sizeof(HashNode));
+	ht->nodes = (HashNode *) zshcalloc(newsize * sizeof(HashNode));
 	ht->hsize = newsize;
     } else {
 	/* else we just re-zero the current nodes array */
@@ -639,7 +639,7 @@ hashdir(char **dirp)
 
     while ((fn = zreaddir(dir, 1))) {
 	if (!cmdnamtab->getnode(cmdnamtab, fn)) {
-	    cn = (Cmdnam) zcalloc(sizeof *cn);
+	    cn = (Cmdnam) zshcalloc(sizeof *cn);
 	    cn->flags = 0;
 	    cn->u.name = dirp;
 	    cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
@@ -654,7 +654,7 @@ hashdir(char **dirp)
 	    (exe[3] == 'E' || exe[3] == 'e') && exe[4] == 0) {
 	    *exe = 0;
 	    if (!cmdnamtab->getnode(cmdnamtab, fn)) {
-		cn = (Cmdnam) zcalloc(sizeof *cn);
+		cn = (Cmdnam) zshcalloc(sizeof *cn);
 		cn->flags = 0;
 		cn->u.name = dirp;
 		cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn);
@@ -1048,7 +1048,7 @@ createaliasnode(char *txt, int flags)
 {
     Alias al;
 
-    al = (Alias) zcalloc(sizeof *al);
+    al = (Alias) zshcalloc(sizeof *al);
     al->flags = flags;
     al->text = txt;
     al->inuse = 0;
diff --git a/Src/hist.c b/Src/hist.c
index 57e429a7d..e40007049 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -771,7 +771,7 @@ hbegin(int dohist)
 	hwend = nohwe;
 	addtoline = nohw;
     } else {
-	chline = hptr = zcalloc(hlinesz = 64);
+	chline = hptr = zshcalloc(hlinesz = 64);
 	chwords = zalloc((chwordlen = 64) * sizeof(short));
 	hgetc = ihgetc;
 	hungetc = ihungetc;
@@ -933,7 +933,7 @@ prepnexthistent(void)
     }
 
     if (histlinect < histsiz) {
-	he = (Histent)zcalloc(sizeof *he);
+	he = (Histent)zshcalloc(sizeof *he);
 	if (!hist_ring)
 	    hist_ring = he->up = he->down = he;
 	else {
diff --git a/Src/init.c b/Src/init.c
index d2f8ec591..291351b9d 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -325,7 +325,7 @@ parseargs(char **argv)
     if(isset(SINGLECOMMAND))
 	opts[INTERACTIVE] &= 1;
     opts[INTERACTIVE] = !!opts[INTERACTIVE];
-    pparams = x = (char **) zcalloc((countlinknodes(paramlist) + 1) * sizeof(char *));
+    pparams = x = (char **) zshcalloc((countlinknodes(paramlist) + 1) * sizeof(char *));
 
     while ((*x++ = (char *)getlinknode(paramlist)));
     free(paramlist);
@@ -1191,9 +1191,9 @@ zsh_main(int argc, char **argv)
 	  break;
     } while (zsh_name);
 
-    /* Not zopenmax() here: it may return a number too big for zcalloc(). */
+    /* Not zopenmax() here: it may return a number too big for zshcalloc(). */
     fdtable_size = 256; /* This grows as necessary, see utils.c:movefd(). */
-    fdtable = zcalloc(fdtable_size);
+    fdtable = zshcalloc(fdtable_size);
 
     createoptiontable();
     emulate(zsh_name, 1);   /* initialises most options */
diff --git a/Src/input.c b/Src/input.c
index f90ac7b00..525a3202a 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -273,9 +273,6 @@ inputline(void)
 	free(ingetcline);
 	return lexstop = errflag = 1;
     }
-    /* Look for a space, to see if this shouldn't be put into history */
-    if (isfirstln)
-	spaceflag = *ingetcline == ' ';
     if (isset(VERBOSE)) {
 	/* Output the whole line read so far. */
 	zputs(ingetcline, stderr);
@@ -374,7 +371,7 @@ inungetc(int c)
 	     * can't back up where we want to.  Instead, we just push it
 	     * onto the input stack as an extra character.
 	     */
-	    char *cback = (char *)zcalloc(2);
+	    char *cback = (char *)zshcalloc(2);
 	    cback[0] = (char) c;
 	    inpush(cback, INP_FREE|INP_CONT, NULL);
 	}
diff --git a/Src/jobs.c b/Src/jobs.c
index c0f43b503..120e4a8e6 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -815,7 +815,7 @@ addproc(pid_t pid, char *text)
     Process pn;
     struct timezone dummy_tz;
 
-    pn = (Process) zcalloc(sizeof *pn);
+    pn = (Process) zshcalloc(sizeof *pn);
     pn->pid = pid;
     if (text)
 	strcpy(pn->text, text);
diff --git a/Src/mem.c b/Src/mem.c
index cea3cec19..83c784165 100644
--- a/Src/mem.c
+++ b/Src/mem.c
@@ -32,7 +32,7 @@
 
 /*
 	There are two ways to allocate memory in zsh.  The first way is
-	to call zalloc/zcalloc, which call malloc/calloc directly.  It
+	to call zalloc/zshcalloc, which call malloc/calloc directly.  It
 	is legal to call realloc() or free() on memory allocated this way.
 	The second way is to call zhalloc/hcalloc, which allocates memory
 	from one of the memory pools on the heap stack.  Such memory pools 
@@ -105,7 +105,8 @@ union mem_align {
 
 static Heap heaps;
 
-/* first heap with free space, not always correct */
+/* a heap with free space, not always correct (it will be the last heap
+ * if that was newly allocated but it may also be another one) */
 
 static Heap fheap;
 
@@ -115,9 +116,13 @@ static Heap fheap;
 mod_export Heap
 new_heaps(void)
 {
-    Heap h = heaps;
+    Heap h;
+
+    queue_signals();
+    h = heaps;
 
     fheap = heaps = NULL;
+    unqueue_signals();
 
     return h;
 }
@@ -130,6 +135,7 @@ old_heaps(Heap old)
 {
     Heap h, n;
 
+    queue_signals();
     for (h = heaps; h; h = n) {
 	n = h->next;
 	DPUTS(h->sp, "BUG: old_heaps() with pushed heaps");
@@ -141,6 +147,7 @@ old_heaps(Heap old)
     }
     heaps = old;
     fheap = NULL;
+    unqueue_signals();
 }
 
 /* Temporarily switch to other heaps (or back again). */
@@ -149,10 +156,14 @@ old_heaps(Heap old)
 mod_export Heap
 switch_heaps(Heap new)
 {
-    Heap h = heaps;
+    Heap h;
+
+    queue_signals();
+    h = heaps;
 
     heaps = new;
     fheap = NULL;
+    unqueue_signals();
 
     return h;
 }
@@ -166,6 +177,8 @@ pushheap(void)
     Heap h;
     Heapstack hs;
 
+    queue_signals();
+
 #if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
     h_push++;
 #endif
@@ -177,6 +190,7 @@ pushheap(void)
 	h->sp = hs;
 	hs->used = h->used;
     }
+    unqueue_signals();
 }
 
 /* reset heaps to previous state */
@@ -187,6 +201,8 @@ freeheap(void)
 {
     Heap h, hn, hl = NULL;
 
+    queue_signals();
+
 #if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
     h_free++;
 #endif
@@ -214,6 +230,8 @@ freeheap(void)
 	hl->next = NULL;
     else
 	heaps = NULL;
+
+    unqueue_signals();
 }
 
 /* reset heap to previous state and destroy state information */
@@ -225,6 +243,8 @@ popheap(void)
     Heap h, hn, hl = NULL;
     Heapstack hs;
 
+    queue_signals();
+
 #if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
     h_pop++;
 #endif
@@ -255,6 +275,8 @@ popheap(void)
 	hl->next = NULL;
     else
 	heaps = NULL;
+
+    unqueue_signals();
 }
 
 /* allocate memory from the current memory pool */
@@ -268,16 +290,23 @@ zhalloc(size_t size)
 
     size = (size + H_ISIZE - 1) & ~(H_ISIZE - 1);
 
+    queue_signals();
+
 #if defined(ZSH_MEM) && defined(ZSH_MEM_DEBUG)
     h_m[size < (1024 * H_ISIZE) ? (size / H_ISIZE) : 1024]++;
 #endif
 
     /* find a heap with enough free space */
 
-    for (h = (fheap ? fheap : heaps); h; h = h->next) {
+    for (h = ((fheap && HEAP_ARENA_SIZE >= (size + fheap->used)) ? fheap : heaps);
+	 h; h = h->next) {
 	if (HEAP_ARENA_SIZE >= (n = size + h->used)) {
+	    void *ret;
+
 	    h->used = n;
-	    return arena(h) + n - size;
+	    ret = arena(h) + n - size;
+	    unqueue_signals();
+	    return ret;
 	}
     }
     {
@@ -289,7 +318,6 @@ zhalloc(size_t size)
             /* tricky, see above */
 #endif
 
-	queue_signals();
 	n = HEAP_ARENA_SIZE > size ? HEAPSIZE : size + sizeof(*h);
 	for (hp = NULL, h = heaps; h; hp = h, h = h->next);
 
@@ -338,7 +366,7 @@ zhalloc(size_t size)
 	    hp->next = h;
 	else
 	    heaps = h;
-	fheap = NULL;
+	fheap = h;
 
 	unqueue_signals();
 	return arena(h);
@@ -361,6 +389,7 @@ hrealloc(char *p, size_t old, size_t new)
 
     /* find the heap with p */
 
+    queue_signals();
     for (h = heaps, ph = NULL; h; ph = h, h = h->next)
 	if (p >= arena(h) && p < arena(h) + HEAP_ARENA_SIZE)
 	    break;
@@ -376,9 +405,12 @@ hrealloc(char *p, size_t old, size_t new)
 #ifdef ZSH_MEM_DEBUG
 	    memset(p, 0xff, old);
 #endif
+	    unqueue_signals();
 	    return ptr;
-	} else
+	} else {
+	    unqueue_signals();
 	    return new ? p : NULL;
+	}
     }
 
     DPUTS(p + old != arena(h) + h->used, "BUG: hrealloc more than allocated");
@@ -395,6 +427,7 @@ hrealloc(char *p, size_t old, size_t new)
 #else
 	    zfree(h, HEAPSIZE);
 #endif
+	    unqueue_signals();
 	    return NULL;
 	}
 #ifndef USE_MMAP
@@ -407,6 +440,7 @@ hrealloc(char *p, size_t old, size_t new)
 		heaps = h = (Heap) realloc(h, n);
 	}
 	h->used = new;
+	unqueue_signals();
 	return arena(h);
 #endif
     }
@@ -415,6 +449,7 @@ hrealloc(char *p, size_t old, size_t new)
 #endif
     if (h->used + (new - old) <= HEAP_ARENA_SIZE) {
 	h->used += new - old;
+	unqueue_signals();
 	return p;
     } else {
 	char *t = zhalloc(new);
@@ -423,6 +458,7 @@ hrealloc(char *p, size_t old, size_t new)
 #ifdef ZSH_MEM_DEBUG
 	memset(p, 0xff, old);
 #endif
+	unqueue_signals();
 	return t;
     }
 }
@@ -450,26 +486,30 @@ zalloc(size_t size)
 
     if (!size)
 	size = 1;
+    queue_signals();
     if (!(ptr = (void *) malloc(size))) {
 	zerr("fatal error: out of memory", NULL, 0);
 	exit(1);
     }
+    unqueue_signals();
 
     return ptr;
 }
 
 /**/
 mod_export void *
-zcalloc(size_t size)
+zshcalloc(size_t size)
 {
     void *ptr;
 
     if (!size)
 	size = 1;
+    queue_signals();
     if (!(ptr = (void *) malloc(size))) {
 	zerr("fatal error: out of memory", NULL, 0);
 	exit(1);
     }
+    unqueue_signals();
     memset(ptr, 0, size);
 
     return ptr;
@@ -485,6 +525,7 @@ zcalloc(size_t size)
 mod_export void *
 zrealloc(void *ptr, size_t size)
 {
+    queue_signals();
     if (ptr) {
 	if (size) {
 	    /* Do normal realloc */
@@ -492,44 +533,22 @@ zrealloc(void *ptr, size_t size)
 		zerr("fatal error: out of memory", NULL, 0);
 		exit(1);
 	    }
+	    unqueue_signals();
 	    return ptr;
 	}
 	else
 	    /* If ptr is not NULL, but size is zero, *
 	     * then object pointed to is freed.      */
 	    free(ptr);
+
+	ptr = NULL;
     } else {
 	/* If ptr is NULL, then behave like malloc */
-	return malloc(size);
+	ptr = malloc(size);
     }
+    unqueue_signals();
 
-    return NULL;
-}
-
-/**/
-mod_export char *
-dupstring(const char *s)
-{
-    char *t;
-
-    if (!s)
-	return NULL;
-    t = (char *) zhalloc(strlen((char *)s) + 1);
-    strcpy(t, s);
-    return t;
-}
-
-/**/
-mod_export char *
-ztrdup(const char *s)
-{
-    char *t;
-
-    if (!s)
-	return NULL;
-    t = (char *)zalloc(strlen((char *)s) + 1);
-    strcpy(t, s);
-    return t;
+    return ptr;
 }
 
 /**/
@@ -1118,7 +1137,12 @@ zfree(void *p, int sz)
 	long n = (m_lfree->len - M_MIN - M_KEEP) & ~(m_pgsz - 1);
 
 	m_lfree->len -= n;
+#ifdef HAVE_BRK
 	if (brk(m_high -= n) == -1) {
+#else
+	m_high -= n;
+	if (sbrk(-n) == (void *)-1) {
+#endif /* HAVE_BRK */
 	    DPUTS(1, "MEM: allocation error at brk.");
 	}
 
@@ -1221,6 +1245,7 @@ bin_mem(char *name, char **argv, char *ops, int func)
     char *b, *c, buf[40];
     long u = 0, f = 0, to, cu;
 
+    queue_signals();
     if (ops['v']) {
 	printf("The lower and the upper addresses of the heap. Diff gives\n");
 	printf("the difference between them, i.e. the size of the heap.\n\n");
@@ -1349,6 +1374,7 @@ bin_mem(char *name, char **argv, char *ops, int func)
     if (h_m[1024])
 	printf("big\t%d\n", h_m[1024]);
 
+    unqueue_signals();
     return 0;
 }
 
diff --git a/Src/module.c b/Src/module.c
index 63e0dc2f6..e943fb397 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -88,6 +88,27 @@ register_module(char *n, Module_func setup, Module_func boot,
     zaddlinknode(linkedmodules, m);
 }
 
+/* Print an alias. */
+
+/**/
+static void
+printmodalias(Module m, char *ops)
+{
+    if (ops['L']) {
+	printf("zmodload -A ");
+	if (m->nam[0] == '-')
+	    fputs("-- ", stdout);
+	quotedzputs(m->nam, stdout);
+	putchar('=');
+	quotedzputs(m->u.alias, stdout);
+    } else {
+	nicezputs(m->nam, stdout);
+	fputs(" -> ", stdout);
+	nicezputs(m->u.alias, stdout);
+    }
+    putchar('\n');
+}
+
 /* Check if a module is linked in. */
 
 /**/
@@ -164,6 +185,15 @@ addwrapper(Module m, FuncWrap w)
 {
     FuncWrap p, q;
 
+    /*
+     * We can't add a wrapper to an alias, since it's supposed
+     * to behave identically to the resolved module.  This shouldn't
+     * happen since we usually add wrappers when a real module is
+     * loaded.
+     */
+    if (m->flags & MOD_ALIAS)
+	return 1;
+
     if (w->flags & WRAPF_ADDED)
 	return 1;
     for (p = wrappers, q = NULL; p; q = p, p = p->next);
@@ -196,7 +226,7 @@ mod_export LinkList modules;
 int
 add_autobin(char *nam, char *module)
 {
-    Builtin bn = zcalloc(sizeof(*bn));
+    Builtin bn = zshcalloc(sizeof(*bn));
     bn->nam = ztrdup(nam);
     bn->optstr = ztrdup(module);
     return addbuiltin(bn);
@@ -256,6 +286,9 @@ deletewrapper(Module m, FuncWrap w)
 {
     FuncWrap p, q;
 
+    if (m->flags & MOD_ALIAS)
+	return 1;
+
     if (w->flags & WRAPF_ADDED) {
 	for (p = wrappers, q = NULL; p && p != w; q = p, p = p->next);
 
@@ -292,7 +325,8 @@ load_and_bind(const char *fn)
 	int err = loadbind(0, (void *) addbuiltin, ret);
 	for (node = firstnode(modules); !err && node; incnode(node)) {
 	    Module m = (Module) getdata(node);
-	    if (m->u.handle && !(m->flags & MOD_LINKED))
+	    if (!(m->flags & MOD_ALIAS) &&
+		m->u.handle && !(m->flags & MOD_LINKED))
 		err |= loadbind(0, m->u.handle, ret);
 	}
 
@@ -431,21 +465,78 @@ do_load_module(char const *name)
 /**/
 #endif /* !DYNAMIC */
 
+/*
+ * Find a module in the list.
+ * If aliasp is non-zero, resolve any aliases to the underlying module.
+ * If namep is set, this is set to point to the last alias value resolved,
+ *   even if that module was not loaded. or the module name if no aliases.
+ *   Hence this is always the physical module to load in a chain of aliases.
+ * Return NULL if the module named is not stored as a structure, or if we were
+ * resolving aliases and the final module named is not stored as a
+ * structure.
+ *
+ * TODO: now we have aliases, there may be some merit in using a hash
+ * table instead of a linked list.
+ */
 /**/
 static LinkNode
-find_module(const char *name)
+find_module(const char *name, int aliasp, const char **namep)
 {
     Module m;
     LinkNode node;
 
     for (node = firstnode(modules); node; incnode(node)) {
 	m = (Module) getdata(node);
-	if (!strcmp(m->nam, name))
+	if (!strcmp(m->nam, name)) {
+	    if (aliasp && (m->flags & MOD_ALIAS)) {
+		if (namep)
+		    *namep = m->u.alias;
+		return find_module(m->u.alias, 1, namep);
+	    }
+	    if (namep)
+		*namep = m->nam;
 	    return node;
+	}
     }
     return NULL;
 }
 
+/*
+ * Unlink and free a module node from the linked list.
+ */
+
+/**/
+static void
+delete_module(LinkNode node)
+{
+    Module m = (Module) remnode(modules, node);
+
+    if (m->flags & MOD_ALIAS)
+	zsfree(m->u.alias);
+    zsfree(m->nam);
+    if (m->deps)
+	freelinklist(m->deps, freestr);
+    zfree(m, sizeof(*m));
+}
+
+/**/
+mod_export int
+module_loaded(const char *name)
+{
+    LinkNode node;
+    Module m;
+
+    return ((node = find_module(name, 1, NULL)) &&
+	    (m = ((Module) getdata(node)))->u.handle &&
+	    !(m->flags & MOD_UNLOAD));
+}
+
+/*
+ * Setup and cleanup functions:  we don't search for aliases here,
+ * since they should have been resolved before we try to load or unload
+ * the module.
+ */
+
 /**/
 #ifdef DYNAMIC
 
@@ -654,7 +745,7 @@ modname_ok(char const *p)
 }
 
 /**/
-int
+mod_export int
 load_module(char const *name)
 {
     Module m;
@@ -667,11 +758,19 @@ load_module(char const *name)
 	zerr("invalid module name `%s'", name, 0);
 	return 0;
     }
-    if (!(node = find_module(name))) {
+    /*
+     * The following function call may alter name to the final name in a
+     * chain of aliases.  This makes sure the actual module loaded
+     * is the right one.
+     */
+    queue_signals();
+    if (!(node = find_module(name, 1, &name))) {
 	if (!(linked = module_linked(name)) &&
-	    !(handle = do_load_module(name)))
+	    !(handle = do_load_module(name))) {
+	    unqueue_signals();
 	    return 0;
-	m = zcalloc(sizeof(*m));
+	}
+	m = zshcalloc(sizeof(*m));
 	m->nam = ztrdup(name);
 	if (handle) {
 	    m->u.handle = handle;
@@ -685,23 +784,26 @@ load_module(char const *name)
 	if ((set = setup_module(m)) || boot_module(m)) {
 	    if (!set)
 		finish_module(m);
-	    remnode(modules, node);
-	    zsfree(m->nam);
-	    zfree(m, sizeof(*m));
-	    m->flags &= ~MOD_SETUP;
+	    delete_module(node);
+	    unqueue_signals();
 	    return 0;
 	}
 	m->flags |= MOD_INIT_S | MOD_INIT_B;
 	m->flags &= ~MOD_SETUP;
+	unqueue_signals();
 	return 1;
     } 
     m = (Module) getdata(node);
-    if (m->flags & MOD_SETUP)
+    if (m->flags & MOD_SETUP) {
+	unqueue_signals();
 	return 1;
+    }
     if (m->flags & MOD_UNLOAD)
 	m->flags &= ~MOD_UNLOAD;
-    else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle)
+    else if ((m->flags & MOD_LINKED) ? m->u.linked : m->u.handle) {
+	unqueue_signals();
 	return 1;
+    }
     if (m->flags & MOD_BUSY) {
 	zerr("circular dependencies for module %s", name, 0);
 	return 0;
@@ -711,14 +813,17 @@ load_module(char const *name)
 	for (n = firstnode(m->deps); n; incnode(n))
 	    if (!load_module((char *) getdata(n))) {
 		m->flags &= ~MOD_BUSY;
+		unqueue_signals();
 		return 0;
 	    }
     m->flags &= ~MOD_BUSY;
     if (!m->u.handle) {
 	handle = NULL;
 	if (!(linked = module_linked(name)) &&
-	    !(handle = do_load_module(name)))
+	    !(handle = do_load_module(name))) {
+	    unqueue_signals();
 	    return 0;
+	}
 	if (handle) {
 	    m->u.handle = handle;
 	    m->flags |= MOD_SETUP;
@@ -732,6 +837,7 @@ load_module(char const *name)
 	    else
 		m->u.linked = NULL;
 	    m->flags &= ~MOD_SETUP;
+	    unqueue_signals();
 	    return 0;
 	}
 	m->flags |= MOD_INIT_S;
@@ -744,10 +850,12 @@ load_module(char const *name)
 	else
 	    m->u.handle = NULL;
 	m->flags &= ~MOD_SETUP;
+	unqueue_signals();
 	return 0;
     }
     m->flags |= MOD_INIT_B;
     m->flags &= ~MOD_SETUP;
+    unqueue_signals();
     return 1;
 }
 
@@ -761,38 +869,50 @@ load_module(char const *name)
 
 /**/
 mod_export int
-require_module(char *nam, char *module, int res, int test)
+require_module(char *nam, const char *module, int res, int test)
 {
     Module m = NULL;
     LinkNode node;
+    int ret = 1;
 
-    /* First see if the module is linked in. */
-    for (node = firstnode(linkedmodules); node; incnode(node)) {
-	if (!strcmp((char *) getdata(node), nam))
-	    return 1;
-    }
-    node = find_module(module);
+    /* Resolve aliases and actual loadable module as for load_module */
+    queue_signals();
+    node = find_module(module, 1, &module);
     if (node && (m = ((Module) getdata(node)))->u.handle &&
 	!(m->flags & MOD_UNLOAD)) {
 	if (test) {
+	    unqueue_signals();
 	    zwarnnam(nam, "module %s already loaded.", module, 0);
 	    return 0;
 	}
     } else
-	return load_module(module);
+	ret = load_module(module);
+    unqueue_signals();
 
-    return 1;
+    return ret;
 }
 
 /**/
 void
-add_dep(char *name, char *from)
+add_dep(const char *name, char *from)
 {
     LinkNode node;
     Module m;
 
-    if (!(node = find_module(name))) {
-	m = zcalloc(sizeof(*m));
+    /*
+     * If we were passed an alias, we must resolve it to a final
+     * module name (and maybe add the corresponding struct), since otherwise
+     * we would need to check all modules to see if they happen
+     * to be aliased to the same thing to implement depencies properly.
+     *
+     * This should mean that an attempt to add an alias which would
+     * have the same name as a module which has dependencies is correctly
+     * rejected, because then the module named already exists as a non-alias.
+     * Better make sure.  (There's no problem making a an alias which
+     * *points* to a module with dependencies, of course.)
+     */
+    if (!(node = find_module(name, 1, &name))) {
+	m = zshcalloc(sizeof(*m));
 	m->nam = ztrdup(name);
 	zaddlinknode(modules, m);
     } else
@@ -838,12 +958,23 @@ autoloadscan(HashNode hn, int printflags)
 int
 bin_zmodload(char *nam, char **args, char *ops, int func)
 {
-    if ((ops['b'] || ops['c'] || ops['p'] || ops['f']) &&
-	!(ops['a'] || ops['u'])) {
+    int ops_bcpf = ops['b'] || ops['c'] || ops['p'] || ops['f'];
+    int ops_au = ops['a'] || ops['u'];
+    int ret = 1;
+
+    if (ops_bcpf && !ops_au) {
 	zwarnnam(nam, "-b, -c, -f, and -p must be combined with -a or -u",
 		 NULL, 0);
 	return 1;
     }
+    if (ops['A'] || ops['R']) {
+	if (ops_bcpf || ops_au || ops['d'] || (ops['R'] && ops['e'])) {
+	    zwarnnam(nam, "illegal flags combined with -A or -R", NULL, 0);
+	    return 1;
+	}
+	if (!ops['e'])
+	    return bin_zmodload_alias(nam, args, ops);
+    }
     if (ops['d'] && ops['a']) {
 	zwarnnam(nam, "-d cannot be combined with -a", NULL, 0);
 	return 1;
@@ -857,24 +988,137 @@ bin_zmodload(char *nam, char **args, char *ops, int func)
 	zwarnnam(nam, "-e cannot be combined with other options", NULL, 0);
 	return 1;
     }
+    queue_signals();
     if (ops['e'])
-	return bin_zmodload_exist(nam, args, ops);
+	ret = bin_zmodload_exist(nam, args, ops);
     else if (ops['d'])
-	return bin_zmodload_dep(nam, args, ops);
+	ret = bin_zmodload_dep(nam, args, ops);
     else if ((ops['a'] || ops['b']) && !(ops['c'] || ops['p'] || ops['f']))
-	return bin_zmodload_auto(nam, args, ops);
+	ret = bin_zmodload_auto(nam, args, ops);
     else if (ops['c'] && !(ops['b'] || ops['p']))
-	return bin_zmodload_cond(nam, args, ops);
+	ret = bin_zmodload_cond(nam, args, ops);
     else if (ops['f'] && !(ops['b'] || ops['p']))
-	return bin_zmodload_math(nam, args, ops);
+	ret = bin_zmodload_math(nam, args, ops);
     else if (ops['p'] && !(ops['b'] || ops['c']))
-	return bin_zmodload_param(nam, args, ops);
+	ret = bin_zmodload_param(nam, args, ops);
     else if (!(ops['a'] || ops['b'] || ops['c'] || ops['p']))
-	return bin_zmodload_load(nam, args, ops);
+	ret = bin_zmodload_load(nam, args, ops);
     else
 	zwarnnam(nam, "use only one of -b, -c, or -p", NULL, 0);
+    unqueue_signals();
 
-    return 1;
+    return ret;
+}
+
+/**/
+static int
+bin_zmodload_alias(char *nam, char **args, char *ops)
+{
+    /*
+     * TODO: while it would be too nasty to have aliases, as opposed
+     * to real loadable modules, with dependencies --- just what would
+     * we need to load when, exactly? --- there is in principle no objection
+     * to making it possible to force an alias onto an existing unloaded
+     * module which has dependencies.  This would simply transfer
+     * the dependencies down the line to the aliased-to module name.
+     * This is actually useful, since then you can alias zsh/zle=mytestzle
+     * to load another version of zle.  But then what happens when the
+     * alias is removed?  Do you transfer the dependencies back? And
+     * suppose other names are aliased to the same file?  It might be
+     * kettle of fish best left unwormed.
+     */
+    LinkNode node;
+    Module m;
+    int ret = 0;
+
+    if (!*args) {
+	if (ops['R']) {
+	    zwarnnam(nam, "no module alias to remove", NULL, 0);
+	    return 1;
+	}
+	for (node = firstnode(modules); node; incnode(node)) {
+	    m = (Module) getdata(node);
+	    if (m->flags & MOD_ALIAS)
+		printmodalias(m, ops);
+	}
+	return 0;
+    }
+
+    for (; !ret && *args; args++) {
+	char *eqpos = strchr(*args, '=');
+	char *aliasname = eqpos ? eqpos+1 : NULL;
+	if (eqpos)
+	    *eqpos = '\0';
+	if (!modname_ok(*args)) {
+	    zwarnnam(nam, "invalid module name `%s'", *args, 0);
+	    return 1;
+	}
+	if (ops['R']) {
+	    if (aliasname) {
+		zwarnnam(nam, "bad syntax for removing module alias: %s",
+			 *args, 0);
+		return 1;
+	    }
+	    node = find_module(*args, 0, NULL);
+	    if (node) {
+		m = (Module) getdata(node);
+		if (!(m->flags & MOD_ALIAS)) {
+		    zwarnnam(nam, "module is not an alias: %s", *args, 0);
+		    ret = 1;
+		    break;
+		}
+		delete_module(node);
+	    } else {
+		zwarnnam(nam, "no such module alias: %s", *args, 0);
+		return 1;
+	    }
+	} else {
+	    if (aliasname) {
+		const char *mname = aliasname;
+		if (!modname_ok(aliasname)) {
+		    zwarnnam(nam, "invalid module name `%s'", aliasname, 0);
+		    return 1;
+		}
+		find_module(aliasname, 1, &mname);
+		if (!strcmp(mname, *args)) {
+		    zwarnnam(nam, "module alias would refer to itself: %s",
+			     *args, 0);
+		    return 1;
+		}
+		node = find_module(*args, 0, NULL);
+		if (node) {
+		    m = (Module) getdata(node);
+		    if (!(m->flags & MOD_ALIAS)) {
+			zwarnnam(nam, "module is not an alias: %s", *args, 0);
+			return 1;
+		    }
+		    zsfree(m->u.alias);
+		} else {
+		    m = (Module) zshcalloc(sizeof(*m));
+		    m->nam = ztrdup(*args);
+		    m->flags = MOD_ALIAS;
+		    zaddlinknode(modules, m);
+		}
+		m->u.alias = ztrdup(aliasname);
+	    } else {
+		if ((node = find_module(*args, 0, NULL))) {
+		    m = (Module) getdata(node);
+		    if (m->flags & MOD_ALIAS)
+			printmodalias(m, ops);
+		    else {
+			zwarnnam(nam, "module is not an alias: %s",
+				 *args, 0);
+			return 1;
+		    }
+		} else {
+		    zwarnnam(nam, "no such module alias: %s", *args, 0);
+		    return 1;
+		}
+	    }
+	}
+    }
+
+    return 0;
 }
 
 /**/
@@ -883,28 +1127,33 @@ bin_zmodload_exist(char *nam, char **args, char *ops)
 {
     LinkNode node;
     Module m;
+    char *modname;
 
     if (!*args) {
 	for (node = firstnode(modules); node; incnode(node)) {
 	    m = (Module) getdata(node);
+	    modname = m->nam;
+	    if (m->flags & MOD_ALIAS) {
+		LinkNode node2;
+		if (ops['A'] && (node2 = find_module(m->u.alias, 1, NULL)))
+		    m = (Module) getdata(node2);
+		else
+		    continue;
+	    } 
 	    if (m->u.handle && !(m->flags & MOD_UNLOAD)) {
-		nicezputs(m->nam, stdout);
+		nicezputs(modname, stdout);
 		putchar('\n');
 	    }
 	}
 	return 0;
     } else {
-	int ret = 0, f;
+	int ret = 0;
 
 	for (; !ret && *args; args++) {
-	    f = 0;
-	    for (node = firstnode(modules);
-		 !f && node; incnode(node)) {
-		m = (Module) getdata(node);
-		if (m->u.handle && !(m->flags & MOD_UNLOAD))
-		    f = !strcmp(*args, m->nam);
-	    }
-	    ret = !f;
+	    if (!(node = find_module(*args, 1, NULL))
+		|| !(m = (Module) getdata(node))->u.handle
+		|| (m->flags & MOD_UNLOAD))
+		ret = 1;
 	}
 	return ret;
     }
@@ -916,23 +1165,24 @@ bin_zmodload_dep(char *nam, char **args, char *ops)
 {
     LinkNode node;
     Module m;
-    if(ops['u']) {
-	/* remove dependencies */
-	char *tnam = *args++;
-	node = find_module(tnam);
+    if (ops['u']) {
+	/* remove dependencies, which can't pertain to aliases */
+	const char *tnam = *args++;
+	node = find_module(tnam, 1, &tnam);
 	if (!node)
 	    return 0;
 	m = (Module) getdata(node);
-	if(*args && m->deps) {
+	if (*args && m->deps) {
 	    do {
-		for(node = firstnode(m->deps); node; incnode(node))
-		    if(!strcmp(*args, getdata(node))) {
-			zsfree(getdata(node));
-			remnode(m->deps, node);
+		LinkNode dnode;
+		for (dnode = firstnode(m->deps); dnode; incnode(dnode))
+		    if (!strcmp(*args, getdata(dnode))) {
+			zsfree(getdata(dnode));
+			remnode(m->deps, dnode);
 			break;
 		    }
 	    } while(*++args);
-	    if(empty(m->deps)) {
+	    if (empty(m->deps)) {
 		freelinklist(m->deps, freestr);
 		m->deps = NULL;
 	    }
@@ -942,19 +1192,16 @@ bin_zmodload_dep(char *nam, char **args, char *ops)
 		m->deps = NULL;
 	    }
 	}
-	if (!m->deps && !m->u.handle) {
-	    remnode(modules, node);
-	    zsfree(m->nam);
-	    zfree(m, sizeof(*m));
-	}
+	if (!m->deps && !m->u.handle)
+	    delete_module(node);
 	return 0;
-    } else if(!args[0] || !args[1]) {
+    } else if (!args[0] || !args[1]) {
 	/* list dependencies */
 	for (node = firstnode(modules); node; incnode(node)) {
 	    m = (Module) getdata(node);
 	    if (m->deps && (!args[0] || !strcmp(args[0], m->nam))) {
 		LinkNode n;
-		if(ops['L']) {
+		if (ops['L']) {
 		    printf("zmodload -d ");
 		    if(m->nam[0] == '-')
 			fputs("-- ", stdout);
@@ -979,7 +1226,7 @@ bin_zmodload_dep(char *nam, char **args, char *ops)
 	int ret = 0;
 	char *tnam = *args++;
 
-	for(; *args; args++)
+	for (; *args; args++)
 	    add_dep(tnam, *args);
 	return ret;
     }
@@ -1099,7 +1346,7 @@ bin_zmodload_math(char *nam, char **args, char *ops)
     int ret = 0;
 
     if (ops['u']) {
-	/* remove autoloaded conditions */
+	/* remove autoloaded math functions */
 	for (; *args; args++) {
 	    MathFunc f = getmathfunc(*args, 0);
 
@@ -1108,7 +1355,7 @@ bin_zmodload_math(char *nam, char **args, char *ops)
 		    zwarnnam(nam, "%s: no such math function", *args, 0);
 		    ret = 1;
 		}
-	    } else if (f->flags & CONDF_ADDED) {
+	    } else if (f->flags & MFF_ADDED) {
 		zwarnnam(nam, "%s: math function is already defined", *args, 0);
 		ret = 1;
 	    } else
@@ -1130,7 +1377,7 @@ bin_zmodload_math(char *nam, char **args, char *ops)
 	}
 	return 0;
     } else {
-	/* add autoloaded conditions */
+	/* add autoloaded math functions */
 	char *modnam;
 
 	modnam = *args++;
@@ -1209,6 +1456,15 @@ bin_zmodload_param(char *nam, char **args, char *ops)
 int
 unload_module(Module m, LinkNode node)
 {
+    /*
+     * Only unload the real module, so resolve aliases.
+     */
+    if (m->flags & MOD_ALIAS) {
+	LinkNode node = find_module(m->u.alias, 1, NULL);
+	if (!node)
+	    return 1;
+	m = (Module) getdata(node);
+    }
     if ((m->flags & MOD_INIT_S) &&
 	!(m->flags & MOD_UNLOAD) &&
 	((m->flags & MOD_LINKED) ?
@@ -1242,7 +1498,7 @@ unload_module(Module m, LinkNode node)
 	    LinkNode n;
 
 	    for (n = firstnode(m->deps); n; incnode(n)) {
-		LinkNode dn = find_module((char *) getdata(n));
+		LinkNode dn = find_module((char *) getdata(n), 1, NULL);
 		Module dm;
 
 		if (dn && (dm = (Module) getdata(dn)) &&
@@ -1280,9 +1536,7 @@ unload_module(Module m, LinkNode node)
 		if (!node)
 		    return 1;
 	    }
-	    remnode(modules, node);
-	    zsfree(m->nam);
-	    zfree(m, sizeof(*m));
+	    delete_module(node);
 	}
     }
     return 0;
@@ -1297,8 +1551,9 @@ bin_zmodload_load(char *nam, char **args, char *ops)
     int ret = 0;
     if(ops['u']) {
 	/* unload modules */
+	const char *mname = *args;
 	for(; *args; args++) {
-	    node = find_module(*args);
+	    node = find_module(*args, 1, &mname);
 	    if (node) {
 		LinkNode mn, dn;
 		int del = 0;
@@ -1307,11 +1562,11 @@ bin_zmodload_load(char *nam, char **args, char *ops)
 		    m = (Module) getdata(mn);
 		    if (m->deps && m->u.handle)
 			for (dn = firstnode(m->deps); dn; incnode(dn))
-			    if (!strcmp((char *) getdata(dn), *args)) {
+			    if (!strcmp((char *) getdata(dn), mname)) {
 				if (m->flags & MOD_UNLOAD)
 				    del = 1;
 				else {
-				    zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", *args, 0);
+				    zwarnnam(nam, "module %s is in use by another module and cannot be unloaded", mname, 0);
 				    ret = 1;
 				    goto cont;
 				}
@@ -1335,7 +1590,7 @@ bin_zmodload_load(char *nam, char **args, char *ops)
 	/* list modules */
 	for (node = firstnode(modules); node; incnode(node)) {
 	    m = (Module) getdata(node);
-	    if (m->u.handle && !(m->flags & MOD_UNLOAD)) {
+	    if (m->u.handle && !(m->flags & (MOD_UNLOAD|MOD_ALIAS))) {
 		if(ops['L']) {
 		    printf("zmodload ");
 		    if(m->nam[0] == '-')
@@ -1761,12 +2016,14 @@ add_autoparam(char *nam, char *module)
 {
     Param pm;
 
+    queue_signals();
     if ((pm = (Param) gethashnode2(paramtab, nam)))
 	unsetparam_pm(pm, 0, 1);
 
-    pm = setsparam(ztrdup(nam), ztrdup(module));
+    pm = setsparam(nam, ztrdup(module));
 
     pm->flags |= PM_AUTOLOAD;
+    unqueue_signals();
 }
 
 /* List of math functions. */
@@ -1862,6 +2119,8 @@ add_automathfunc(char *nam, char *module)
 
 	return 1;
     }
+    f->flags &= ~MFF_ADDED; /* still to autoload, not added yet */
+
     return 0;
 }
 
diff --git a/Src/params.c b/Src/params.c
index 255260467..aa80bcc78 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -318,7 +318,7 @@ scancopyparams(HashNode hn, int flags)
 {
     /* Going into a real parameter, so always use permanent storage */
     Param pm = (Param)hn;
-    Param tpm = (Param) zcalloc(sizeof *tpm);
+    Param tpm = (Param) zshcalloc(sizeof *tpm);
     tpm->nam = ztrdup(pm->nam);
     copyparam(tpm, pm, 0);
     addhashnode(outtable, tpm->nam, tpm);
@@ -687,7 +687,7 @@ createparam(char *name, int flags)
 	    pm->ct = 0;
 	    oldpm = pm->old;
 	} else {
-	    pm = (Param) zcalloc(sizeof *pm);
+	    pm = (Param) zshcalloc(sizeof *pm);
 	    if ((pm->old = oldpm)) {
 		/*
 		 * needed to avoid freeing oldpm, but we do take it
@@ -1753,7 +1753,7 @@ setarrvalue(Value v, char **val)
 	if (v->end <= n)
 	    ll += n - v->end + 1;
 
-	p = new = (char **) zcalloc(sizeof(char *) * (ll + 1));
+	p = new = (char **) zshcalloc(sizeof(char *) * (ll + 1));
 
 	for (i = 0; i < v->start; i++)
 	    *p++ = i < n ? ztrdup(*q++) : ztrdup("");
diff --git a/Src/parse.c b/Src/parse.c
index b3072201a..ddb163986 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -2064,7 +2064,7 @@ dupeprog(Eprog p, int heap)
     r->len = p->len;
     r->npats = p->npats;
     pp = r->pats = (heap ? (Patprog *) hcalloc(r->len) :
-		    (Patprog *) zcalloc(r->len));
+		    (Patprog *) zshcalloc(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)));
@@ -3161,7 +3161,7 @@ dump_autoload(char *nam, char *file, int on, char *ops, int func)
 
     for (n = firstfdhead(h), e = (FDHead) (h + fdheaderlen(h)); n < e;
 	 n = nextfdhead(n)) {
-	shf = (Shfunc) zcalloc(sizeof *shf);
+	shf = (Shfunc) zshcalloc(sizeof *shf);
 	shf->flags = on;
 	shf->funcdef = mkautofn(shf);
 	shfunctab->addnode(shfunctab, ztrdup(fdname(n) + fdhtail(n)), shf);
diff --git a/Src/pattern.c b/Src/pattern.c
index b5f89f53c..be9f3b568 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -1430,9 +1430,9 @@ pattryrefs(Patprog prog, char *string, int *nump, int *begp, int *endp)
 		char **matcharr, **mbeginarr, **mendarr;
 		char numbuf[DIGBUFSIZE];
 
-		matcharr = zcalloc(palen*sizeof(char *));
-		mbeginarr = zcalloc(palen*sizeof(char *));
-		mendarr = zcalloc(palen*sizeof(char *));
+		matcharr = zshcalloc(palen*sizeof(char *));
+		mbeginarr = zshcalloc(palen*sizeof(char *));
+		mendarr = zshcalloc(palen*sizeof(char *));
 
 		sp = patbeginp;
 		ep = patendp;
@@ -1786,7 +1786,7 @@ patmatch(Upat prog)
 			oldsyncstr = syncstrp->p;
 			if (!patinlen)
 			    patinlen = strlen(patinstart)+1;
-			syncstrp->p = (unsigned char *)zcalloc(patinlen);
+			syncstrp->p = (unsigned char *)zshcalloc(patinlen);
 			while ((ret = patmatch(P_OPERAND(scan)))) {
 			    unsigned char *syncpt;
 			    char savchar, *testptr;
@@ -1909,7 +1909,7 @@ patmatch(Upat prog)
 			    if (!ptrp->p) {
 				if (!patinlen)
 				    patinlen = strlen((char *)patinstart)+1;
-				ptrp->p = (unsigned char *)zcalloc(patinlen);
+				ptrp->p = (unsigned char *)zshcalloc(patinlen);
 				pfree = 1;
 			    }
 			    ptr = ptrp->p + (patinput - patinstart);
diff --git a/Src/prompt.c b/Src/prompt.c
index d5df9d1ce..43dc12bee 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -171,7 +171,7 @@ promptexpand(char *s, int ns, char *rs, char *Rs)
     rstring = rs;
     Rstring = Rs;
     fm = s;
-    bp = bufline = buf = zcalloc(bufspc = 256);
+    bp = bufline = buf = zshcalloc(bufspc = 256);
     bp1 = NULL;
     trunclen = 0;
     putpromptchar(1, '\0');
diff --git a/Src/utils.c b/Src/utils.c
index e2a6ab60f..cf202009f 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -293,7 +293,7 @@ slashsplit(char *s)
     int t0;
 
     if (!*s)
-	return (char **) zcalloc(sizeof(char **));
+	return (char **) zshcalloc(sizeof(char **));
 
     for (t = s, t0 = 0; *t; t++)
 	if (*t == '/')
@@ -541,7 +541,7 @@ adduserdir(char *s, char *t, int flags, int always)
     }
 
     /* add the name */
-    nd = (Nameddir) zcalloc(sizeof *nd);
+    nd = (Nameddir) zshcalloc(sizeof *nd);
     nd->flags = flags;
     nd->dir = ztrdup(t);
     /* The variables PWD and OLDPWD are not to be displayed as ~PWD etc. */
@@ -1771,7 +1771,7 @@ zjoin(char **arr, int delim, int heap)
 	len += strlen(*s) + 1;
     if (!len)
 	return heap? "" : ztrdup("");
-    ptr = ret = (heap ? (char *) hcalloc(len) : (char *) zcalloc(len));
+    ptr = ret = (heap ? (char *) hcalloc(len) : (char *) zshcalloc(len));
     for (s = arr; *s; s++) {
 	strucpy(&ptr, *s);
 	if (delim)
@@ -1841,7 +1841,7 @@ spacesplit(char *s, int allownull, int heap, int quote)
     int l = sizeof(*ret) * (wordcount(s, NULL, -!allownull) + 1);
     char *(*dup)(const char *) = (heap ? dupstring : ztrdup);
 
-    ptr = ret = (heap ? (char **) hcalloc(l) : (char **) zcalloc(l));
+    ptr = ret = (heap ? (char **) hcalloc(l) : (char **) zshcalloc(l));
 
     if (quote) {
 	/*
@@ -1868,7 +1868,7 @@ spacesplit(char *s, int allownull, int heap, int quote)
 	findsep(&s, NULL, quote);
 	if (s > t || allownull) {
 	    *ptr = (heap ? (char *) hcalloc((s - t) + 1) :
-		    (char *) zcalloc((s - t) + 1));
+		    (char *) zshcalloc((s - t) + 1));
 	    ztrncpy(*ptr++, t, s - t);
 	} else
 	    *ptr++ = dup(nulstring);
@@ -2040,7 +2040,7 @@ sepjoin(char **s, char *sep, int heap)
     }
     sl = strlen(sep);
     for (t = s, l = 1 - sl; *t; l += strlen(*t) + sl, t++);
-    r = p = (heap ? (char *) hcalloc(l) : (char *) zcalloc(l));
+    r = p = (heap ? (char *) hcalloc(l) : (char *) zshcalloc(l));
     t = s;
     while (*t) {
 	strucpy(&p, *t);
@@ -2064,13 +2064,13 @@ sepsplit(char *s, char *sep, int allownull, int heap)
     sl = strlen(sep);
     n = wordcount(s, sep, 1);
     r = p = (heap ? (char **) hcalloc((n + 1) * sizeof(char *)) :
-	     (char **) zcalloc((n + 1) * sizeof(char *)));
+	     (char **) zshcalloc((n + 1) * sizeof(char *)));
 
     for (t = s; n--;) {
 	tt = t;
 	findsep(&t, sep, 0);
 	*p = (heap ? (char *) hcalloc(t - tt + 1) :
-	      (char *) zcalloc(t - tt + 1));
+	      (char *) zshcalloc(t - tt + 1));
 	strncpy(*p, tt, t - tt);
 	(*p)[t - tt] = '\0';
 	p++;