about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorTanaka Akira <akr@users.sourceforge.net>1999-04-15 18:15:04 +0000
committerTanaka Akira <akr@users.sourceforge.net>1999-04-15 18:15:04 +0000
commitba4f5e80ec9d7e145718e79fed6e57a852c86c12 (patch)
treeae29f2dfb81bb4e20b015610d85ce5f5a2d96eda /Src
parent850fb2e7f94b4e0e9fbf3538ad9e3c44c9fed74b (diff)
downloadzsh-ba4f5e80ec9d7e145718e79fed6e57a852c86c12.tar.gz
zsh-ba4f5e80ec9d7e145718e79fed6e57a852c86c12.tar.xz
zsh-ba4f5e80ec9d7e145718e79fed6e57a852c86c12.zip
zsh-3.1.5-pws-8 zsh-3.1.5-pws-8
Diffstat (limited to 'Src')
-rw-r--r--Src/Makefile.in8
-rw-r--r--Src/Zle/comp.h5
-rw-r--r--Src/Zle/comp1.c7
-rw-r--r--Src/Zle/compctl.c36
-rw-r--r--Src/Zle/zle_hist.c10
-rw-r--r--Src/Zle/zle_keymap.c4
-rw-r--r--Src/Zle/zle_main.c5
-rw-r--r--Src/Zle/zle_misc.c49
-rw-r--r--Src/Zle/zle_params.c28
-rw-r--r--Src/Zle/zle_refresh.c12
-rw-r--r--Src/Zle/zle_tricky.c115
-rw-r--r--Src/Zle/zle_vi.c5
-rw-r--r--Src/builtin.c6
-rw-r--r--Src/init.c30
-rw-r--r--Src/params.c8
-rw-r--r--Src/signames1.awk19
-rw-r--r--Src/signames2.awk100
-rw-r--r--Src/text.c3
-rw-r--r--Src/utils.c2
-rw-r--r--Src/zsh.mdd9
20 files changed, 358 insertions, 103 deletions
diff --git a/Src/Makefile.in b/Src/Makefile.in
index 27891e92a..1b5256e16 100644
--- a/Src/Makefile.in
+++ b/Src/Makefile.in
@@ -85,7 +85,9 @@ modobjs: headers rm-modobjs-tmp
 rm-modobjs-tmp:
 	rm -f stamp-modobjs.tmp
 
-Makemod modules.index prep: modules-bltin
+@@config.mk@@
+
+Makemod modules.index prep: modules-bltin $(CONFIG_INCS)
 	( cd $(sdir_top) && $(SHELL) $(subdir)/mkmodindex.sh $(subdir) ) \
 	    > modules.index.tmp
 	@if cmp -s modules.index.tmp modules.index; then \
@@ -200,6 +202,4 @@ install.modules uninstall.modules \
 modobjs modules headers proto $(MAIN_OBJS): Makemod
 	@$(MAKE) -f Makemod $(MAKEDEFS) $@
 
-# ========== DEPENDENCIES FOR MAINTENANCE ==========
-
-@@config.mk@@
+$(MAIN_OBJS): $(sdir)/zsh.h
diff --git a/Src/Zle/comp.h b/Src/Zle/comp.h
index 5f263557a..124ae454a 100644
--- a/Src/Zle/comp.h
+++ b/Src/Zle/comp.h
@@ -211,6 +211,7 @@ struct cmatch {
     int brpl;			/* the place where to put the brace prefix */
     int brsl;			/* ...and the suffix */
     char *rems;			/* when to remove the suffix */
+    char *remf;			/* shell function to call for suffix-removal */
 };
 
 #define CMF_FILE     1		/* this is a file */
@@ -228,6 +229,7 @@ struct cmlist {
 };
 
 struct cmatcher {
+    int refc;			/* reference counter */
     Cmatcher next;		/* next matcher */
     int flags;			/* see CMF_* below */
     Cpattern line;		/* what matches on the line */
@@ -280,5 +282,4 @@ struct cline {
 #define CAF_MENU     2
 #define CAF_NOSORT   4
 #define CAF_ALT      8
-#define CAF_FIGNORE 16
-#define CAF_MATCH   32
+#define CAF_MATCH   16
diff --git a/Src/Zle/comp1.c b/Src/Zle/comp1.c
index a5e35bc3c..77fe0a1fe 100644
--- a/Src/Zle/comp1.c
+++ b/Src/Zle/comp1.c
@@ -49,7 +49,7 @@ void (*makecompparamsptr) _((void));
 /* pointers to functions required by compctl and defined by zle */
 
 /**/
-void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char **));
+void (*addmatchesptr) _((char *, char *, char *, char *, char *, char *, char *, char *, char *, char *, int, int, Cmatcher, char **));
 
 /**/
 char *(*comp_strptr) _((int*,int*));
@@ -61,7 +61,7 @@ int (*getcpatptr) _((char *, int, char *, int));
 void (*makecomplistcallptr) _((Compctl));
 
 /**/
-void (*makecomplistctlptr) _((int));
+int (*makecomplistctlptr) _((int));
 
 /* Hash table for completion info for commands */
  
@@ -249,6 +249,9 @@ freecmatcher(Cmatcher m)
 {
     Cmatcher n;
 
+    if (!m || --(m->refc))
+	return;
+
     while (m) {
 	n = m->next;
 	freecpattern(m->line);
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index dcc206c96..cec71fc5b 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -38,6 +38,7 @@
 #define COMP_DEFAULT	(1<<2)	/* -D */
 #define COMP_FIRST	(1<<3)	/* -T */
 #define COMP_REMOVE	(1<<4)
+#define COMP_LISTMATCH	(1<<5)	/* -L and -M */
 
 #define COMP_SPECIAL (COMP_COMMAND|COMP_DEFAULT|COMP_FIRST)
 
@@ -82,6 +83,7 @@ cpcmatcher(Cmatcher m)
     while (m) {
 	*p = n = (Cmatcher) zalloc(sizeof(struct cmatcher));
 
+	n->refc = 1;
 	n->next = NULL;
 	n->flags = m->flags;
 	n->line = cpcpattern(m->line);
@@ -712,7 +714,9 @@ get_compctl(char *name, char ***av, Compctl cc, int first, int isdef, int cl)
 		cct.mask2 |= CC_NOSORT;
 		break;
 	    case 'M':
-		if ((*argv)[1]) {
+		if (cclist & COMP_LIST) {
+		    cclist |= COMP_LISTMATCH;
+		} else if ((*argv)[1]) {
 		    if ((cct.matcher =
 			 parse_cmatcher(name, (cct.mstr = (*argv) + 1))) ==
 			pcm_err) {
@@ -1572,7 +1576,7 @@ bin_compctl(char *name, char **argv, char *ops, int func)
     /* If no commands and no -C, -T, or -D, print all the compctl's *
      * If some flags (other than -C, -T, or -D) were given, then    *
      * only print compctl containing those flags.                   */
-    if (!*argv && !(cclist & COMP_SPECIAL)) {
+    if (!*argv && !(cclist & (COMP_SPECIAL|COMP_LISTMATCH))) {
 	Patcomp pc;
 
 	for (pc = patcomps; pc; pc = pc->next)
@@ -1619,6 +1623,8 @@ bin_compctl(char *name, char **argv, char *ops, int func)
 	    printcompctl("", &cc_default, 0, 0);
 	if (cclist & COMP_FIRST)
 	    printcompctl("", &cc_first, 0, 0);
+	if (cclist & COMP_LISTMATCH)
+	    print_gmatcher(COMP_LIST);
 	return ret;
     }
 
@@ -1670,6 +1676,7 @@ bin_compadd(char *name, char **argv, char *ops, int func)
     char *p, **sp, *e;
     char *ipre = NULL, *ppre = NULL, *psuf = NULL, *prpre = NULL;
     char *pre = NULL, *suf = NULL, *group = NULL, *m = NULL, *rs = NULL;
+    char *ign = NULL, *rf = NULL;
     int f = 0, a = 0, dm;
     Cmatcher match = NULL;
 
@@ -1692,7 +1699,8 @@ bin_compadd(char *name, char **argv, char *ops, int func)
 		f |= CMF_FILE;
 		break;
 	    case 'F':
-		a |= CAF_FIGNORE;
+		sp = &ign;
+		e = "string expected after -%c";
 		break;
 	    case 'n':
 		f |= CMF_NOLIST;
@@ -1746,9 +1754,15 @@ bin_compadd(char *name, char **argv, char *ops, int func)
 		dm = 1;
 		break;
 	    case 'r':
+		f |= CMF_REMOVE;
 		sp = &rs;
 		e = "string expected after -%c";
 		break;
+	    case 'R':
+		f |= CMF_REMOVE;
+		sp = &rf;
+		e = "function name expected after -%c";
+		break;
 	    case '-':
 		argv++;
 		goto ca_args;
@@ -1782,8 +1796,11 @@ bin_compadd(char *name, char **argv, char *ops, int func)
     if (!*argv)
 	return 1;
 
+    match = cpcmatcher(match);
     addmatchesptr(ipre, ppre, psuf, prpre, pre, suf, group,
-		  rs, f, a, match, argv);
+		  rs, rf, ign, f, a, match, argv);
+    freecmatcher(match);
+
     return 0;
 }
 
@@ -1795,9 +1812,8 @@ bin_compcall(char *name, char **argv, char *ops, int func)
 	zerrnam(name, "can only be called from completion function", NULL, 0);
 	return 1;
     }
-    makecomplistctlptr((ops['T'] ? 0 : CFN_FIRST) |
-		       (ops['D'] ? 0 : CFN_DEFAULT));
-    return 0;
+    return makecomplistctlptr((ops['T'] ? 0 : CFN_FIRST) |
+			      (ops['D'] ? 0 : CFN_DEFAULT));
 }
 
 #define VAR(X) ((void *) (&(X)))
@@ -2016,7 +2032,7 @@ cond_strcl(char **a, int id)
 {
     if (comp_check()) {
 	char *s;
-	int i;
+	int i, ipl;
 
 	if (a[1]) {
 	    s = cond_str(a, 1);
@@ -2029,9 +2045,9 @@ cond_strcl(char **a, int id)
 	    zerr("zle not loaded, zle condition not available", NULL, 0);
 	    return 1;
 	}
-	i = getcpatptr(comp_strptr(NULL, NULL), i, s, id);
+	i = getcpatptr(comp_strptr(&ipl, NULL), i, s, id);
 	if (i != -1) {
-	    ignore_prefix(i);
+	    ignore_prefix(i - ipl);
 	    return 1;
 	}
     }
diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c
index e6b385652..a4b3866e5 100644
--- a/Src/Zle/zle_hist.c
+++ b/Src/Zle/zle_hist.c
@@ -663,10 +663,7 @@ doisearch(int dir)
     static char *previous_search = NULL;
     static int previous_search_len = 0;
 
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
 
     strcpy(ibuf, ISEARCH_PROMPT);
     memcpy(ibuf + NORM_PROMPT_POS, (dir == 1) ? "fwd" : "bck", 3);
@@ -948,10 +945,7 @@ getvisrchstr(void)
 	zsfree(visrchstr);
 	visrchstr = NULL;
     }
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
     statusline = sbuf;
     sbuf[0] = (visrchsense == -1) ? '?' : '/';
     selectkeymap("main", 1);
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index 1ffe6f156..1baa3a845 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -108,7 +108,9 @@ static HashTable keymapnamtab;
 
 /* key sequence reading data */
 
-static char *keybuf;
+/**/
+char *keybuf;
+
 static int keybuflen, keybufsz = 20;
 
 /* last command executed with execute-named-command */
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index ca7a7fe19..277d154a6 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -792,10 +792,7 @@ describekeybriefly(void)
 
     if (statusline)
 	return;
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
     statusline = "Describe key briefly: _";
     statusll = strlen(statusline);
     zrefresh();
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 4b5df9cde..ea8874010 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -612,10 +612,7 @@ executenamedcommand(char *prmt)
     char *ptr;
     char *okeymap = curkeymapname;
 
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
     cmdbuf = halloc(l + NAMLEN + 2);
     strcpy(cmdbuf, prmt);
     statusline = cmdbuf;
@@ -767,6 +764,11 @@ executenamedcommand(char *prmt)
 /**/
 int suffixlen[257];
 
+/* Shell function to call to remove the suffix. */
+
+/**/
+static char *suffixfunc;
+
 /* Set up suffix: the last n characters are a suffix that should be *
  * removed in the usual word end conditions.                        */
 
@@ -801,9 +803,13 @@ makeparamsuffix(int br, int n)
 
 /**/
 void
-makesuffixstr(char *s, int n)
+makesuffixstr(char *f, char *s, int n)
 {
-    if (s) {
+    if (f) {
+	zsfree(suffixfunc);
+	suffixfunc = ztrdup(f);
+	suffixlen[0] = n;
+    } else if (s) {
 	int inv, i, v, z = 0;
 
 	if (*s == '^' || *s == '!') {
@@ -845,10 +851,33 @@ makesuffixstr(char *s, int n)
 void
 iremovesuffix(int c)
 {
-    int sl = suffixlen[c];
-    if(sl) {
-	backdel(sl);
-	invalidatelist();
+    if (suffixfunc) {
+	List l = getshfunc(suffixfunc);
+
+	if (l != &dummy_list) {
+	    LinkList args = newlinklist();
+	    char buf[20];
+	    int osc = sfcontext;
+
+	    sprintf(buf, "%d", suffixlen[0]);
+	    addlinknode(args, suffixfunc);
+	    addlinknode(args, buf);
+
+	    startparamscope();
+	    makezleparams(0);
+	    sfcontext = SFC_COMPLETE;
+	    doshfunc(suffixfunc, l, args, 0, 1);
+	    sfcontext = osc;
+	    endparamscope();
+	}
+	zsfree(suffixfunc);
+	suffixfunc = NULL;
+    } else {
+	int sl = suffixlen[c];
+	if(sl) {
+	    backdel(sl);
+	    invalidatelist();
+	}
     }
     fixsuffix();
 }
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index 74f905ef4..7e15d3d8b 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -65,6 +65,8 @@ static struct zleparam {
         zleunsetfn, NULL },
     { "LASTWIDGET", PM_SCALAR | PM_READONLY, NULL, FN(get_lwidget),
         zleunsetfn, NULL },
+    { "keys", PM_ARRAY | PM_READONLY, NULL, FN(get_keys),
+        zleunsetfn, NULL },
     { NULL, 0, NULL, NULL, NULL, NULL }
 };
 
@@ -216,3 +218,29 @@ get_lwidget(Param pm)
 {
     return (lbindk ? lbindk->nam : "");
 }
+
+/**/
+static char **
+get_keys(Param pm)
+{
+    char **r, **q, *p, *k, c;
+
+    r = (char **) halloc((strlen(keybuf) + 1) * sizeof(char *));
+    for (q = r, p = keybuf; (c = *p); q++, p++) {
+	k = *q = (char *) halloc(5);
+	if (c & 0x80) {
+	    *k++ = 'M';
+	    *k++ = '-';
+	    c &= 0x7f;
+	}
+	if (c < 32 || c == 0x7f) {
+	    *k++ = '^';
+	    c ^= 64;
+	}
+	*k++ = c;
+	*k = '\0';
+    }
+    *q = NULL;
+
+    return r;
+}
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index c8d6c70a7..9e07676e8 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -60,6 +60,11 @@ int showinglist;
 /**/
 int clearflag;
 
+/* Non-zero if zrefresh() should clear the list below the prompt. */
+
+/**/
+int clearlist;
+
 #ifdef HAVE_SELECT
 /* cost of last update */
 /**/
@@ -248,6 +253,13 @@ zrefresh(void)
     if (inlist)
 	return;
 
+    if (clearlist) {
+	invalidatelist();
+	moveto(0, 0);
+	clearflag = 0;
+	resetneeded = 1;
+	clearlist = 0;
+    }
 #ifdef HAVE_SELECT
     cost = 0;			/* reset */
 #endif
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index f1285da8c..f1078ef11 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -212,6 +212,10 @@ static LinkList ccstack;
 
 static Cmlist mstack;
 
+/* A list with references to all matcher we used. */
+
+static LinkList matchers;
+
 /* A heap of free Cline structures. */
 
 static Cline freecl;
@@ -2454,10 +2458,10 @@ instmatch(Cmatch m)
 /**/
 void
 addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
-	   char *suf, char *group, char *rems, 
+	   char *suf, char *group, char *rems, char *remf, char *ign,
 	   int flags, int aflags, Cmatcher match, char **argv)
 {
-    char *s, *t, *e, *te, *ms, *lipre = NULL, *lpre, *lsuf;
+    char *s, *t, *e, *te, *ms, *lipre = NULL, *lpre, *lsuf, **aign = NULL;
     int lpl, lsl, i, pl, sl, test, bpl, bsl, lsm, llpl;
     Aminfo ai;
     Cline lc = NULL;
@@ -2477,22 +2481,26 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 	mst.next = mstack;
 	mst.matcher = match;
 	mstack = &mst;
+	addlinknode(matchers, match);
+	match->refc++;
     }
     if ((aflags & CAF_MENU) && isset(AUTOMENU))
 	usemenu = 1;
+    if (ign)
+	aign = get_user_var(ign);
+
     SWITCHHEAPS(compheap) {
 	HEAPALLOC {
 	    if (aflags & CAF_MATCH) {
-		ctokenize(lipre = dupstring(compiprefix));
-		remnulargs(lipre);
-		ctokenize(lpre = dupstring(compprefix));
-		remnulargs(lpre);
+		lipre = dupstring(compiprefix);
+		lpre = dupstring(compprefix);
 		llpl = strlen(lpre);
-		ctokenize(lsuf = dupstring(compsuffix));
-		remnulargs(lsuf);
+		lsuf = dupstring(compsuffix);
 	    }
 	    if (ipre)
 		ipre = (lipre ? dyncat(lipre, ipre) : dupstring(ipre));
+	    else if (lipre)
+		ipre = lipre;
 	    if (ppre) {
 		ppre = dupstring(ppre);
 		lpl = strlen(ppre);
@@ -2520,7 +2528,10 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 		if (aflags & CAF_NOSORT)
 		    mgroup->flags |= CGF_NOSORT;
 	    }
-	    if (rems)
+	    if (remf) {
+		remf = dupstring(remf);
+		rems = NULL;
+	    } else if (rems)
 		rems = dupstring(rems);
     	    if (ai->pprefix) {
 		if (pre)
@@ -2535,8 +2546,8 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 		ms = NULL;
 		bpl = brpl;
 		bsl = brsl;
-		if ((!psuf || !*psuf) && (aflags & CAF_FIGNORE)) {
-		    char **pt = fignore;
+		if ((!psuf || !*psuf) && aign) {
+		    char **pt = aign;
 		    int filell;
 
 		    for (test = 1; test && *pt; pt++)
@@ -2635,6 +2646,7 @@ addmatches(char *ipre, char *ppre, char *psuf, char *prpre, char *pre,
 		cm->flags = flags;
 		cm->brpl = bpl;
 		cm->brsl = bsl;
+		cm->remf = remf;
 		cm->rems = rems;
 		addlinknode(l, cm);
 
@@ -2936,7 +2948,7 @@ addmatch(char *s, char *t)
     cm->flags = mflags | isf;
     cm->brpl = bpl;
     cm->brsl = bsl;
-    cm->rems = NULL;
+    cm->rems = cm->remf = NULL;
     addlinknode(l, cm);
 
     /* One more match for this explanation. */
@@ -3259,17 +3271,20 @@ static void
 docompletion(char *s, int lst, int incmd)
 {
     HEAPALLOC {
+	LinkNode n;
+
 	pushheap();
 
 	ainfo = fainfo = NULL;
+	matchers = newlinklist();
 
 	/* Make sure we have the completion list and compctl. */
 	if (makecomplist(s, incmd, lst)) {
 	    /* Error condition: feeeeeeeeeeeeep(). */
 	    feep();
+	    clearlist = 1;
 	    goto compend;
 	}
-
 	if (lst == COMP_LIST_COMPLETE)
 	    /* All this and the guy only wants to see the list, sigh. */
 	    showinglist = -2;
@@ -3324,6 +3339,9 @@ docompletion(char *s, int lst, int incmd)
 	    }
 	}
       compend:
+	for (n = firstnode(matchers); n; incnode(n))
+	    freecmatcher((Cmatcher) getdata(n));
+
 	ll = strlen((char *)line);
 	if (cs > ll)
 	    cs = ll;
@@ -3460,13 +3478,26 @@ static int
 makecomplist(char *s, int incmd, int lst)
 {
     struct cmlist ms;
-    Cmlist m = cmatcher;
+    Cmlist m;
 
     /* If we already have a list from a previous execution of this *
      * function, skip the list building code.                      */
     if (validlist)
 	return !nmatches;
 
+    if ((m = cmatcher)) {
+	Cmlist mm, *mp = &mm;
+
+	for (; m; m = m->next) {
+	    *mp = (Cmlist) halloc(sizeof(struct cmlist));
+	    (*mp)->matcher = m->matcher;
+	    (*mp)->next = NULL;
+	    mp = &((*mp)->next);
+	    addlinknode(matchers, m->matcher);
+	    m->matcher->refc++;
+	}
+	m = mm;
+    }
     compmatcher = 1;
     for (;;) {
 	if (m) {
@@ -3613,11 +3644,13 @@ static int cdepth = 0;
 #define MAX_CDEPTH 16
 
 /**/
-void
+int
 makecomplistctl(int flags)
 {
+    int ret;
+
     if (cdepth == MAX_CDEPTH)
-	return;
+	return 0;
 
     cdepth++;
     SWITCHHEAPS(compheap) {
@@ -3641,9 +3674,10 @@ makecomplistctl(int flags)
 	    *q = NULL;
 	    offs = lip + lp;
 	    incompfunc = 2;
-	    makecomplistglobal(str,
-			       (!clwpos && !strcmp(compcontext, "command")),
-			       COMP_COMPLETE, flags);
+	    ret = makecomplistglobal(str,
+				     (!clwpos &&
+				      !strcmp(compcontext, "command")),
+				     COMP_COMPLETE, flags);
 	    incompfunc = 1;
 	    offs = ooffs;
 	    compnmatches = mnum;
@@ -3656,13 +3690,15 @@ makecomplistctl(int flags)
 	} LASTALLOC;
     } SWITCHBACKHEAPS;
     cdepth--;
+
+    return ret;
 }
 
 /* This function gets the compctls for the given command line and *
  * adds all completions for them. */
 
 /**/
-static void
+static int
 makecomplistglobal(char *os, int incmd, int lst, int flags)
 {
     Compctl cc;
@@ -3694,46 +3730,48 @@ makecomplistglobal(char *os, int incmd, int lst, int flags)
     } else if (linredir)
 	/* In redirections use default completion. */
 	cc = &cc_default;
-    else {
+    else
 	/* Otherwise get the matches for the command. */
-	makecomplistcmd(os, incmd, flags);
-	cc = NULL;
-    }
+	return makecomplistcmd(os, incmd, flags);
+
     if (cc) {
 	/* First, use the -T compctl. */
 	if (!(flags & CFN_FIRST)) {
 	    makecomplistcc(&cc_first, os, incmd);
 
 	    if (!(ccont & CC_CCCONT))
-		return;
+		return 0;
 	}
 	makecomplistcc(cc, os, incmd);
+	return 1;
     }
+    return 0;
 }
 
 /* This produces the matches for a command. */
 
 /**/
-static void
+static int
 makecomplistcmd(char *os, int incmd, int flags)
 {
     Compctl cc;
     Compctlp ccp;
     char *s;
+    int ret = 0;
 
     /* First, use the -T compctl. */
     if (!(flags & CFN_FIRST)) {
 	makecomplistcc(&cc_first, os, incmd);
 
 	if (!(ccont & CC_CCCONT))
-	    return;
+	    return 0;
     }
     /* Then search the pattern compctls, with the command name and the *
      * full pathname of the command. */
     if (cmdstr) {
-	makecomplistpc(os, incmd);
+	ret |= makecomplistpc(os, incmd);
 	if (!(ccont & CC_CCCONT))
-	    return;
+	    return ret;
     }
     /* If the command string starts with `=', try the path name of the *
      * command. */
@@ -3758,31 +3796,36 @@ makecomplistcmd(char *os, int incmd, int flags)
 	    (ccp = (Compctlp) compctltab->getnode(compctltab, s)) &&
 	    (cc = ccp->cc))))) {
 	if (flags & CFN_DEFAULT)
-	    return;
+	    return ret;
 	cc = &cc_default;
-    }
+    } else
+	ret|= 1;
     makecomplistcc(cc, os, incmd);
+    return ret;
 }
 
 /* This add the matches for the pattern compctls. */
 
 /**/
-static void
+static int
 makecomplistpc(char *os, int incmd)
 {
     Patcomp pc;
     Comp pat;
     char *s = findcmd(cmdstr, 1);
+    int ret = 0;
 
     for (pc = patcomps; pc; pc = pc->next) {
 	if ((pat = parsereg(pc->pat)) &&
 	    (domatch(cmdstr, pat, 0) ||
 	     (s && domatch(s, pat, 0)))) {
 	    makecomplistcc(pc->cc, os, incmd);
+	    ret |= 2;
 	    if (!(ccont & CC_CCCONT))
-		return;
+		return ret;
 	}
     }
+    return ret;
 }
 
 /* This produces the matches for one compctl. */
@@ -4111,6 +4154,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	ms.next = mstack;
 	ms.matcher = cc->matcher;
 	mstack = &ms;
+	addlinknode(matchers, cc->matcher);
+	cc->matcher->refc++;
     }
     /* Insert the prefix (compctl -P), if any. */
     if (cc->prefix) {
@@ -5225,6 +5270,7 @@ dupmatch(Cmatch m)
     r->brpl = m->brpl;
     r->brsl = m->brsl;
     r->rems = ztrdup(m->rems);
+    r->remf = ztrdup(m->remf);
 
     return r;
 }
@@ -5337,6 +5383,7 @@ freematch(Cmatch m)
     zsfree(m->psuf);
     zsfree(m->prpre);
     zsfree(m->rems);
+    zsfree(m->remf);
 
     zfree(m, sizeof(m));
 }
@@ -5591,7 +5638,7 @@ do_single(Cmatch m)
 	if (menuwe) {
 	    menuend += menuinsc;
 	    if (m->flags & CMF_REMOVE) {
-		makesuffixstr(m->rems, menuinsc);
+		makesuffixstr(m->remf, m->rems, menuinsc);
 		if (menuinsc == 1)
 		    suffixlen[STOUC(m->suf[0])] = 1;
 	    }
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index a116921b4..2e4fb4a32 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -816,10 +816,7 @@ viswapcase(void)
 void
 vicapslockpanic(void)
 {
-    invalidatelist();
-    moveto(0, 0);
-    clearflag = 0;
-    resetneeded = 1; 
+    clearlist = 1;
     zbeep();
     statusline = "press a lowercase key to continue";
     statusll = strlen(statusline);
diff --git a/Src/builtin.c b/Src/builtin.c
index 2b77c57bc..fc9b113ca 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -56,7 +56,7 @@ static struct builtin builtins[] =
     BUILTIN("disown", 0, bin_fg, 0, -1, BIN_DISOWN, NULL, NULL),
     BUILTIN("echo", BINF_PRINTOPTS | BINF_ECHOPTS, bin_print, 0, -1, BIN_ECHO, "neE", "-"),
     BUILTIN("echotc", 0, bin_echotc, 1, -1, 0, NULL, NULL),
-    BUILTIN("emulate", 0, bin_emulate, 1, 1, 0, "R", NULL),
+    BUILTIN("emulate", 0, bin_emulate, 1, 1, 0, "LR", NULL),
     BUILTIN("enable", 0, bin_enable, 0, -1, BIN_ENABLE, "afmr", NULL),
     BUILTIN("eval", BINF_PSPECIAL, bin_eval, 0, -1, BIN_EVAL, NULL, NULL),
     BUILTIN("exit", BINF_PSPECIAL, bin_break, 0, 1, BIN_EXIT, NULL, NULL),
@@ -643,7 +643,7 @@ set_pwd_env(void)
     pm = (Param) paramtab->getnode(paramtab, "OLDPWD");
     if (!(pm->flags & PM_EXPORTED)) {
 	pm->flags |= PM_EXPORTED;
-	pm->env = addenv("PWD", pwd);
+	pm->env = addenv("OLDPWD", oldpwd);
     }
 }
 
@@ -3051,6 +3051,8 @@ int
 bin_emulate(char *nam, char **argv, char *ops, int func)
 {
     emulate(*argv, ops['R']);
+    if (ops['L'])
+	dosetopt(LOCALOPTIONS, 1, 0);
     return 0;
 }
 
diff --git a/Src/init.c b/Src/init.c
index 10013c52b..d66d157c9 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -890,6 +890,20 @@ init_bltinmods(void)
     mod.nam = NULL;
 }
 
+/**/
+void
+noop_function(void)
+{
+    /* do nothing */
+}
+
+/**/
+void
+noop_function_int(int nothing)
+{
+    /* do nothing */
+}
+
 /* ZLE entry point pointers.  They are defined here because the initial *
  * values depend on whether ZLE is linked in or not -- if it is, we     *
  * avoid wasting space with the fallback functions.  No other source    *
@@ -898,7 +912,7 @@ init_bltinmods(void)
 #ifdef LINKED_XMOD_zle
 
 /**/
-ZleVoidFn trashzleptr;
+ZleVoidFn trashzleptr = noop_function;
 /**/
 ZleVoidFn gotwordptr;
 /**/
@@ -921,20 +935,6 @@ ZleReadFn zlereadptr = fallback_zleread;
 # endif /* !UNLINKED_XMOD_zle */
 
 /**/
-void
-noop_function(void)
-{
-    /* do nothing */
-}
-
-/**/
-void
-noop_function_int(int nothing)
-{
-    /* do nothing */
-}
-
-/**/
 # ifdef UNLINKED_XMOD_zle
 
 /**/
diff --git a/Src/params.c b/Src/params.c
index f91a448a1..88b5fdf73 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -246,6 +246,10 @@ IPDEF9F("path", &path, "PATH", PM_RESTRICTED),
 };
 #undef BR
 
+#define IS_UNSET_VALUE(V) \
+	((V) && (!(V)->pm || ((V)->pm->flags & PM_UNSET) || \
+		 !(V)->pm->nam || !*(V)->pm->nam))
+
 static Param argvparam;
 
 /* hash table containing the parameters */
@@ -966,7 +970,7 @@ getindex(char **pptr, Value v)
     if (*tbrack == Outbrack)
 	*tbrack = ']';
     if ((s[0] == '*' || s[0] == '@') && s[1] == ']') {
-	if (v->isarr && s[0] == '@')
+	if ((v->isarr || IS_UNSET_VALUE(v)) && s[0] == '@')
 	    v->isarr |= SCANPM_ISVAR_AT;
 	v->a = 0;
 	v->b = -1;
@@ -1205,6 +1209,8 @@ getarrvalue(Value v)
 
     if (!v)
 	return arrdup(nular);
+    else if (IS_UNSET_VALUE(v))
+	return arrdup(&nular[1]);
     if (v->inv) {
 	char buf[DIGBUFSIZE];
 
diff --git a/Src/signames1.awk b/Src/signames1.awk
new file mode 100644
index 000000000..27d21ac7b
--- /dev/null
+++ b/Src/signames1.awk
@@ -0,0 +1,19 @@
+# This is an awk script which finds out what the possibilities for
+# the signal names are, and dumps them out so that cpp can turn them
+# into numbers.  Since we don't need to decide here what the
+# real signals are, we can afford to be generous about definitions,
+# in case the definitions are in terms of other definitions.
+# However, we need to avoid definitions with parentheses, which will
+# mess up the syntax.
+BEGIN { printf "#include <signal.h>\n\n" }
+
+/^[\t ]*#[\t ]*define[\t _]*SIG[A-Z][A-Z0-9]*[\t ][\t ]*[^(\t ]/ { 
+    sigindex = index($0, "SIG")
+    sigtail = substr($0, sigindex, 80)
+    split(sigtail, tmp)
+    signam = substr(tmp[1], 4, 20)
+    if (substr($0, sigindex-1, 1) == "_")
+        printf("XXNAMES XXSIG%s _SIG%s\n", signam, signam)
+    else
+        printf("XXNAMES XXSIG%s SIG%s\n", signam, signam)
+}
diff --git a/Src/signames2.awk b/Src/signames2.awk
new file mode 100644
index 000000000..3aea76ee3
--- /dev/null
+++ b/Src/signames2.awk
@@ -0,0 +1,100 @@
+#
+# {g,n}awk script to generate signames.c
+# This version relies on the previous output of the preprocessor
+# on sigtmp.c, sigtmp.out, which is in turn generated by signames1.awk.
+#
+# NB: On SunOS 4.1.3 - user-functions don't work properly, also \" problems
+# Without 0 + hacks some nawks compare numbers as strings
+#
+/^XXNAMES XXSIG[A-Z][A-Z0-9]* [1-9][0-9]*/ {
+    sigindex = index($0, "SIG")
+    sigtail = substr($0, sigindex, 80)
+    split(sigtail, tmp)
+    signam = substr(tmp[1], 4, 20)
+    signum = tmp[2]
+    if (sig[signum] == "") {
+	sig[signum] = signam
+	if (0 + max < 0 + signum && signum < 60)
+	    max = signum
+	if (signam == "ABRT")   { msg[signum] = "abort" }
+	if (signam == "ALRM")   { msg[signum] = "alarm" }
+	if (signam == "BUS")    { msg[signum] = "bus error" }
+	if (signam == "CHLD")   { msg[signum] = "death of child" }
+	if (signam == "CLD")    { msg[signum] = "death of child" }
+	if (signam == "CONT")   { msg[signum] = "continued" }
+	if (signam == "EMT")    { msg[signum] = "EMT instruction" }
+	if (signam == "FPE")    { msg[signum] = "floating point exception" }
+	if (signam == "HUP")    { msg[signum] = "hangup" }
+	if (signam == "ILL")    { msg[signum] = "illegal hardware instruction" }
+	if (signam == "INFO")   { msg[signum] = "status request from keyboard" }
+	if (signam == "INT")    { msg[signum] = "interrupt" }
+	if (signam == "IO")     { msg[signum] = "i/o ready" }
+	if (signam == "IOT")    { msg[signum] = "IOT instruction" }
+	if (signam == "KILL")   { msg[signum] = "killed" }
+	if (signam == "LOST")	{ msg[signum] = "resource lost" }
+	if (signam == "PIPE")   { msg[signum] = "broken pipe" }
+	if (signam == "POLL")	{ msg[signum] = "pollable event occurred" }
+	if (signam == "PROF")   { msg[signum] = "profile signal" }
+	if (signam == "PWR")    { msg[signum] = "power fail" }
+	if (signam == "QUIT")   { msg[signum] = "quit" }
+	if (signam == "SEGV")   { msg[signum] = "segmentation fault" }
+	if (signam == "SYS")    { msg[signum] = "invalid system call" }
+	if (signam == "TERM")   { msg[signum] = "terminated" }
+	if (signam == "TRAP")   { msg[signum] = "trace trap" }
+	if (signam == "URG")	{ msg[signum] = "urgent condition" }
+	if (signam == "USR1")   { msg[signum] = "user-defined signal 1" }
+	if (signam == "USR2")   { msg[signum] = "user-defined signal 2" }
+	if (signam == "VTALRM") { msg[signum] = "virtual time alarm" }
+	if (signam == "WINCH")  { msg[signum] = "window size changed" }
+	if (signam == "XCPU")   { msg[signum] = "cpu limit exceeded" }
+	if (signam == "XFSZ")   { msg[signum] = "file size limit exceeded" }
+    }
+}
+
+END {
+    ps = "%s"
+    ifdstr = sprintf("# ifdef USE_SUSPENDED\n\t%csuspended%s%c,\n%s else\n\t%cstopped%s%c,\n# endif\n", 34, ps, 34, "#", 34, ps, 34)
+
+    printf "/** signames.c                                 **/\n"
+    printf "/** architecture-customized signames.c for zsh **/\n"
+    printf "\n"
+    printf "#define SIGCOUNT\t%d\n", max
+    printf "\n"
+    printf "#include %czsh.mdh%c\n", 34, 34
+    printf "\n"
+    printf "/**/\n"
+    printf "char *sigmsg[SIGCOUNT+2] = {\n"
+    printf "\t%c%s%c,\n", 34, "done", 34
+
+    for (i = 1; i <= 0 + max; i++)
+	if (msg[i] == "") {
+	    if (sig[i] == "")
+		printf("\t%c%c,\n", 34, 34)
+	    else if (sig[i] == "STOP")
+		printf ifdstr, " (signal)", " (signal)"
+	    else if (sig[i] == "TSTP")
+		printf ifdstr, "", ""
+	    else if (sig[i] == "TTIN")
+		printf ifdstr, " (tty input)", " (tty input)"
+	    else if (sig[i] == "TTOU")
+		printf ifdstr, " (tty output)", " (tty output)"
+	    else
+		printf("\t%cSIG%s%c,\n", 34, sig[i], 34)
+	} else
+	    printf("\t%c%s%c,\n", 34, msg[i], 34)
+    print "\tNULL"
+    print "};"
+    print ""
+    print "/**/"
+    printf "char *sigs[SIGCOUNT+4] = {\n"
+    printf("\t%cEXIT%c,\n", 34, 34)
+    for (i = 1; i <= 0 + max; i++)
+	if (sig[i] == "")
+	    printf("\t%c%d%c,\n", 34, i, 34)
+	else
+	    printf("\t%c%s%c,\n", 34, sig[i], 34)
+    printf("\t%cZERR%c,\n", 34, 34)
+    printf("\t%cDEBUG%c,\n", 34, 34)
+    print "\tNULL"
+    print "};"
+}
diff --git a/Src/text.c b/Src/text.c
index ec724f27d..88a27495d 100644
--- a/Src/text.c
+++ b/Src/text.c
@@ -415,7 +415,6 @@ getcond(Cond nm, int addpar)
 	    /* Module defined prefix condition. */
 	    char **p = (char **) nm->right;
 
-	    taddstr("-");
 	    taddstr(nm->left);
 	    for (; *p; p++) {
 		taddstr(" ");
@@ -426,7 +425,7 @@ getcond(Cond nm, int addpar)
     case COND_MODI:
 	/* Module defined infix condition. */
 	taddstr(((char **) nm->right)[0]);
-	taddstr(" -");
+	taddstr(" ");
 	taddstr(nm->left);
 	taddstr(" ");
 	taddstr(((char **) nm->right)[1]);
diff --git a/Src/utils.c b/Src/utils.c
index 18a797948..ee06cfeca 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -1160,7 +1160,7 @@ read1char(void)
     char c;
 
     while (read(SHTTY, &c, 1) != 1) {
-	if (errno != EINTR)
+	if (errno != EINTR || errflag)
 	    return -1;
     }
     return STOUC(c);
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index f4a1e4015..214f26681 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -12,8 +12,11 @@ headers="../config.h system.h zsh.h sigcount.h signals.h \
 prototypes.h hashtable.h ztype.h"
 
 :<<\Make
-signames.c: signames.awk ../config.h @SIGNAL_H@
-	$(AWK) -f $(sdir)/signames.awk @SIGNAL_H@ > $@
+signames.c: signames1.awk signames2.awk ../config.h @SIGNAL_H@
+	$(AWK) -f $(sdir)/signames1.awk @SIGNAL_H@ >sigtmp.c
+	$(CPP) sigtmp.c >sigtmp.out
+	$(AWK) -f $(sdir)/signames2.awk sigtmp.out > $@
+	rm -f sigtmp.c sigtmp.out
 
 sigcount.h: signames.c
 	grep 'define.*SIGCOUNT' signames.c > $@
@@ -25,7 +28,7 @@ params.o: version.h
 version.h: $(sdir_top)/Config/version.mk
 	echo '#define ZSH_VERSION "'$(VERSION)'"' > $@
 
-zshpaths.h: FORCE
+zshpaths.h: FORCE Makemod
 	@echo '#define MODULE_DIR "'$(MODDIR)'"' > zshpaths.h.tmp
 	@if cmp -s zshpaths.h zshpaths.h.tmp; then \
 	    rm -f zshpaths.h.tmp; \