about summary refs log tree commit diff
path: root/Src/Zle/zle_tricky.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Zle/zle_tricky.c')
-rw-r--r--Src/Zle/zle_tricky.c128
1 files changed, 68 insertions, 60 deletions
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index 9f4fa0c93..347eb9ffa 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -163,7 +163,7 @@ static int ispattern, haspattern;
  * from the whole word we are completing and the second one from that    *
  * part of the word that was identified as a possible filename.          */
 
-static Comp patcomp, filecomp;
+static Patprog patcomp, filecomp;
 
 /* We store the following prefixes/suffixes:                               *
  * lpre/lsuf -- what's on the line                                         *
@@ -728,7 +728,7 @@ check_param(char *s, int set, int test)
     if ((*p == String || *p == Qstring) && p[1] != Inpar && p[1] != Inbrack) {
 	/* This is really a parameter expression (not $(...) or $[...]). */
 	char *b = p + 1, *e = b;
-	int n = 0, br = 1;
+	int n = 0, br = 1, nest = 0;
 
 	if (*b == Inbrace) {
 	    char *tb = b;
@@ -740,6 +740,10 @@ check_param(char *s, int set, int test)
 	    /* Ignore the possible (...) flags. */
 	    b++, br++;
 	    n = skipparens(Inpar, Outpar, &b);
+
+	    for (tb = p - 1; tb > s && *tb != Outbrace && *tb != Inbrace; tb--);
+	    if (tb > s && *tb == Inbrace && (tb[-1] == String || *tb == Qstring))
+		nest = 1;
 	}
 
 	/* Ignore the stuff before the parameter name. */
@@ -788,9 +792,11 @@ check_param(char *s, int set, int test)
 	     * global variables. */
 
 	    if (set) {
-		if (br >= 2)
+		if (br >= 2) {
 		    mflags |= CMF_PARBR;
-
+		    if (nest)
+			mflags |= CMF_PARNEST;
+		}
 		/* Get the prefix (anything up to the character before the name). */
 		isuf = dupstring(e);
 		untokenize(isuf);
@@ -2542,9 +2548,12 @@ match_str(char *l, char *w, int *bp, int *rwlp, int sfx, int test)
 	    lm = NULL;
 	} else {
 	    /* No matcher and different characters: l does not match w. */
+	    if (test)
+		return 0;
+
 	    abort_match();
 
-	    return (test ? 0 : -1);
+	    return -1;
 	}
     }
     /* If this is a recursive call, we just return if l matched w or not. */
@@ -2600,7 +2609,7 @@ match_str(char *l, char *w, int *bp, int *rwlp, int sfx, int test)
  * and the suffix don't match the word w. */
 
 static char *
-comp_match(char *pfx, char *sfx, char *w, Comp cp,
+comp_match(char *pfx, char *sfx, char *w, Patprog cp,
 	   Cline *clp, int qu, int *bpl, int *bsl, int *exact)
 {
     char *r = NULL;
@@ -2610,7 +2619,7 @@ comp_match(char *pfx, char *sfx, char *w, Comp cp,
 	int wl;
 
 	r = w;
-	if (!domatch(r, cp, 0))
+	if (!pattry(cp, r))
 	    return NULL;
     
 	r = (qu ? quotename(r, NULL) : dupstring(r));
@@ -2868,7 +2877,8 @@ join_strs(int la, char *sa, int lb, char *sb)
 			    *ap += mp->wlen; *alp -= mp->wlen;
 			    *bp += bl; *blp -= bl;
 			    t = 1;
-			}
+			} else
+			    t = 0;
 		    }
 		}
 	    }
@@ -2907,7 +2917,7 @@ cmp_anchors(Cline o, Cline n, int join)
     /* First try the exact strings. */
     if ((!(o->flags & CLF_LINE) && o->wlen == n->wlen &&
 	 (!o->word || !strncmp(o->word, n->word, o->wlen))) ||
-	(line = ((!o->line && !n->line) ||
+	(line = ((!o->line && !n->line && !o->wlen && !n->wlen) ||
 		 (o->llen == n->llen && o->line && n->line &&
 		  !strncmp(o->line, n->line, o->llen))))) {
 	if (line) {
@@ -3419,6 +3429,11 @@ join_clines(Cline o, Cline n)
 	    }
 	    /* Now see if they have matching anchors. If not, cut the list. */
 	    if (!(o->flags & CLF_MID) && !cmp_anchors(o, n, 1)) {
+#if 0
+		/* This used to search forward for matching anchors.
+		 * Unfortunately this does the wrong thing if the prefixes
+		 * before the differing anchors match nicely. */
+
 		Cline t, tn;
 
 		for (t = n; (tn = t->next) && !cmp_anchors(o, tn, 1); t = tn);
@@ -3427,6 +3442,7 @@ join_clines(Cline o, Cline n)
 		    n = tn;
 		    continue;
 		} else {
+#endif
 		    if (o->flags & CLF_SUF)
 			break;
 
@@ -3434,7 +3450,10 @@ join_clines(Cline o, Cline n)
 		    o->wlen = 0;
 		    free_cline(o->next);
 		    o->next = NULL;
+		    o->flags |= CLF_MISS;
+#if 0
 		}
+#endif
 	    }
 	    /* Ok, they are equal, now join the sub-lists. */
 	    if (o->flags & CLF_MID)
@@ -3726,7 +3745,7 @@ int
 addmatches(Cadata dat, char **argv)
 {
     char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL;
-    char **aign = NULL, **dparr = NULL, oaq = autoq;
+    char **aign = NULL, **dparr = NULL, oaq = autoq, *oppre = dat->ppre;
     char *oqp = qipre, *oqs = qisuf, qc;
     int lpl, lsl, pl, sl, bpl, bsl, llpl = 0, llsl = 0, nm = mnum;
     int oisalt = 0, isalt, isexact, doadd, ois = instring, oib = inbackt;
@@ -3734,7 +3753,7 @@ addmatches(Cadata dat, char **argv)
     Cmatch cm;
     struct cmlist mst;
     Cmlist oms = mstack;
-    Comp cp = NULL;
+    Patprog cp = NULL;
     LinkList aparl = NULL, oparl = NULL, dparl = NULL;
 
     if (compquote && (qc = *compquote)) {
@@ -3798,13 +3817,8 @@ addmatches(Cadata dat, char **argv)
 	    /* Get the contents of the completion variables if we have
 	     * to perform matching. */
 	    if (dat->aflags & CAF_MATCH) {
-		if (dat->aflags & CAF_QUOTE) {
-		    lipre = dupstring(compiprefix);
-		    lisuf = dupstring(compisuffix);
-		} else {
-		    lipre = quotename(compiprefix, NULL);
-		    lisuf = quotename(compisuffix, NULL);
-		}
+		lipre = dupstring(compiprefix);
+		lisuf = dupstring(compisuffix);
 		lpre = dupstring(compprefix);
 		lsuf = dupstring(compsuffix);
 		llpl = strlen(lpre);
@@ -3830,7 +3844,7 @@ addmatches(Cadata dat, char **argv)
 		    if (haswilds(tmp)) {
 			if (is)
 			    tmp[llpl] = Star;
-			if ((cp = parsereg(tmp)))
+			if ((cp = patcompile(tmp, 0, NULL)))
 			    haspattern = 1;
 		    }
 		}
@@ -3847,12 +3861,21 @@ addmatches(Cadata dat, char **argv)
 	    else if (lisuf)
 		dat->isuf = lisuf;
 	    if (dat->ppre) {
-		dat->ppre = dupstring(dat->ppre);
+		if (!(dat->aflags & CAF_QUOTE)) {
+		    dat->ppre = quotename(dat->ppre, NULL);
+		    if ((dat->flags & CMF_FILE) &&
+			dat->ppre[0] == '\\' && dat->ppre[1] == '~')
+			chuck(dat->ppre);
+		} else
+		    dat->ppre = dupstring(dat->ppre);
 		lpl = strlen(dat->ppre);
 	    } else
 		lpl = 0;
 	    if (dat->psuf) {
-		dat->psuf = dupstring(dat->psuf);
+		if (!(dat->aflags & CAF_QUOTE))
+		    dat->psuf = quotename(dat->psuf, NULL);
+		else
+		    dat->psuf = dupstring(dat->psuf);
 		lsl = strlen(dat->psuf);
 	    } else
 		lsl = 0;
@@ -3877,7 +3900,7 @@ addmatches(Cadata dat, char **argv)
 		    dat->pre = dupstring(dat->pre);
 		if (dat->suf)
 		    dat->suf = dupstring(dat->suf);
-		if (!dat->prpre && (dat->prpre = dat->ppre)) {
+		if (!dat->prpre && (dat->prpre = oppre)) {
 		    singsub(&(dat->prpre));
 		    untokenize(dat->prpre);
 		} else
@@ -3901,22 +3924,6 @@ addmatches(Cadata dat, char **argv)
 		    dat->rems = NULL;
 		} else if (dat->rems)
 		    dat->rems = dupstring(dat->rems);
-
-		/* Probably quote the prefix and suffix for testing. */
-		if (!(dat->aflags & CAF_QUOTE)) {
-		    if (!cp && (dat->aflags & CAF_MATCH)) {
-			lpre = quotename(lpre, NULL);
-			lsuf = quotename(lsuf, NULL);
-		    }
-		    if (dat->ppre) {
-			dat->ppre = quotename(dat->ppre, NULL);
-			if ((dat->flags & CMF_FILE) &&
-			    dat->ppre[0] == '\\' && dat->ppre[1] == '~')
-			    chuck(dat->ppre);
-		    }
-		    if (dat->psuf)
-			dat->psuf = quotename(dat->psuf, NULL);
-		}
 	    }
 	    /* Walk through the matches given. */
 	    for (; (s = *argv); argv++) {
@@ -4340,7 +4347,7 @@ gen_matches_files(int dirs, int execs, int all)
 		addwhat = execs ? -8 : -5;
 		if (filecomp)
 		    /* If we have a pattern for the filename check, use it. */
-		    test = domatch(n, filecomp, 0);
+		    test = pattry(filecomp, n);
 		else {
 		    /* Otherwise use the prefix and suffix strings directly. */
 		    e = n + strlen(n) - fsl;
@@ -5024,8 +5031,6 @@ comp_str(int *ipl, int *pl, int untok)
 	remnulargs(p);
 	ctokenize(s);
 	remnulargs(s);
-	ctokenize(ip);
-	remnulargs(ip);
     }
     lp = strlen(p);
     ls = strlen(s);
@@ -5563,14 +5568,14 @@ static int
 makecomplistpc(char *os, int incmd)
 {
     Patcomp pc;
-    Comp pat;
+    Patprog 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)))) {
+	if ((pat = patcompile(pc->pat, PAT_STATIC, NULL)) &&
+	    (pattry(pat, cmdstr) ||
+	     (s && pattry(pat, s)))) {
 	    makecomplistcc(pc->cc, os, incmd);
 	    ret |= 2;
 	    if (!(ccont & CC_CCCONT))
@@ -5666,7 +5671,7 @@ makecomplistext(Compctl occ, char *os, int incmd)
 {
     Compctl compc;
     Compcond or, cc;
-    Comp comp;
+    Patprog pprog;
     int compadd, m = 0, d = 0, t, tt, i, j, a, b, ins;
     char *sc = NULL, *s, *ss;
 
@@ -5752,8 +5757,8 @@ makecomplistext(Compctl occ, char *os, int incmd)
 			if (cc->type == CCT_CURPAT ||
 			    cc->type == CCT_WORDPAT) {
 			    tokenize(ss = dupstring(cc->u.s.s[i]));
-			    t = ((comp = parsereg(ss)) &&
-				 domatch(s, comp, 0));
+			    t = ((pprog = patcompile(ss, PAT_STATIC, NULL)) &&
+				 pattry(pprog, s));
 			} else
 			    t = (!strcmp(s, rembslash(cc->u.s.s[i])));
 			break;
@@ -5767,8 +5772,8 @@ makecomplistext(Compctl occ, char *os, int incmd)
 				sc = rembslash(cc->u.l.a[i]);
 			    if (cc->type == CCT_RANGESTR ?
 				!strncmp(s, sc, strlen(sc)) :
-				((comp = parsereg(sc)) &&
-				 domatch(s, comp, 0))) {
+				((pprog = patcompile(sc, PAT_STATIC, 0)) &&
+				 pattry(pprog, s))) {
 				zsfree(s);
 				brange = j + 1;
 				t = 1;
@@ -5785,8 +5790,8 @@ makecomplistext(Compctl occ, char *os, int incmd)
 				    sc = rembslash(cc->u.l.b[i]);
 				if (cc->type == CCT_RANGESTR ?
 				    !strncmp(s, sc, strlen(sc)) :
-				    ((comp = parsereg(sc)) &&
-				     domatch(s, comp, 0))) {
+				    ((pprog = patcompile(sc, PAT_STATIC, 0)) &&
+				     pattry(pprog, s))) {
 				    zsfree(s);
 				    erange = j - 1;
 				    t = clwpos <= erange;
@@ -6050,7 +6055,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	    strcpy(p + rpl + 1, rsuf);
 	} else
 	    strcpy(p + rpl, rsuf);
-	patcomp = parsereg(p);
+	patcomp = patcompile(p, 0, NULL);
 	haspattern = 1;
     }
     if (!patcomp) {
@@ -6148,7 +6153,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 		(!comppatmatch || *comppatmatch == '*'))
 		p[t2++] = Star;
 	    strcpy(p + t2, fsuf);
-	    filecomp = parsereg(p);
+	    filecomp = patcompile(p, 0, NULL);
 	}
 	if (!filecomp) {
 	    untokenize(fpre);
@@ -6567,7 +6572,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
     }
     if (cc->hpat) {
 	/* We have a pattern to take things from the history. */
-	Comp compc = NULL;
+	Patprog pprogc = NULL;
 	char *e, *h, hpatsav;
 	Histent he;
 	int i = addhistnum(curhist,-1,HIST_FOREIGN), n = cc->hnum;
@@ -6577,7 +6582,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 	    char *thpat = dupstring(cc->hpat);
 
 	    tokenize(thpat);
-	    compc = parsereg(thpat);
+	    pprogc = patcompile(thpat, 0, NULL);
 	}
 	/* n holds the number of history line we have to search. */
 	if (!n)
@@ -6594,7 +6599,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
 		/* We now have a word from the history, ignore it *
 		 * if it begins with a quote or `$'.              */
 		if (*h != '\'' && *h != '"' && *h != '`' && *h != '$' &&
-		    (!compc || domatch(h, compc, 0)))
+		    (!pprogc || pattry(pprogc, h)))
 		    /* Otherwise add it if it was matched. */
 		    addmatch(dupstring(h), NULL);
 		if (hpatsav)
@@ -7729,6 +7734,8 @@ do_single(Cmatch m)
 	    minfo.insc++;
 	    if (minfo.we)
 		minfo.end += minfo.insc;
+	    if (m->flags & CMF_PARNEST)
+		havesuff = 1;
 	}
 	if ((m->flags & CMF_FILE) || (m->ripre && isset(AUTOPARAMSLASH))) {
 	    /* If we have a filename or we completed a parameter name      *
@@ -7742,11 +7749,12 @@ do_single(Cmatch m)
 		t = 1;
 	    else {
 		/* Build the path name. */
-		if (m->ripre && !*psuf) {
+		if (m->ripre && !*psuf && !(m->flags & CMF_PARNEST)) {
 		    int ne = noerrs;
 
-		    p = (char *) zhalloc(strlen(m->ripre) + strlen(str) + 1);
-		    sprintf(p, "%s%s", m->ripre, str);
+		    p = (char *) zhalloc(strlen(m->ripre) + strlen(str) + 2);
+		    sprintf(p, "%s%s%c", m->ripre, str,
+			    ((m->flags & CMF_PARBR) ? Outbrace : '\0'));
 		    noerrs = 1;
 		    parsestr(p);
 		    singsub(&p);