about summary refs log tree commit diff
path: root/Src/Zle/compcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Zle/compcore.c')
-rw-r--r--Src/Zle/compcore.c154
1 files changed, 95 insertions, 59 deletions
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 131e86825..09282d42d 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -1187,9 +1187,9 @@ check_param(char *s, int set, int test)
 		return NULL;
 
 	    /* Ignore the possible (...) flags. */
-	    tb = ++b, br++;
-	    if ((qstring ? skipparens('(', ')', &tb) :
-		 skipparens(Inpar, Outpar, &tb)) > 0 || tb - s >= offs) {
+	    b++, br++;
+	    if ((qstring ? skipparens('(', ')', &b) :
+		 skipparens(Inpar, Outpar, &b)) > 0 || b - s > offs) {
 		/*
 		 * We are still within the parameter flags.  There's no
 		 * point trying to do anything clever here with
@@ -1200,14 +1200,6 @@ check_param(char *s, int set, int test)
 		ispar = 2;
 		return NULL;
 	    }
-	    if ((qstring ? '(' : Inpar) == *b) {
-		/*
-		 * We are inside the braces but on the opening paren.
-		 * There is nothing useful to complete here?
-		 */
-		return NULL;
-	    } else
-		b = tb;	/* Skip over the flags */
 
 	    for (tb = p - 1; tb > s && *tb != Outbrace && *tb != Inbrace; tb--);
 	    if (tb > s && *tb == Inbrace && (tb[-1] == String || *tb == Qstring))
@@ -1238,14 +1230,14 @@ check_param(char *s, int set, int test)
 	else if (idigit(*e))
 	    while (idigit(*e))
 		e++;
-	else if ((ie = itype_end(e, IIDENT, 0)) != e) {
+	else if ((ie = itype_end(e, INAMESPC, 0)) != e) {
 	    do {
 		e = ie;
 		if (comppatmatch && *comppatmatch &&
 		    (*e == Star || *e == Quest))
 		    ie = e + 1;
 		else
-		    ie = itype_end(e, IIDENT, 0);
+		    ie = itype_end(e, INAMESPC, 0);
 	    } while (ie != e);
 	}
 
@@ -2081,10 +2073,10 @@ addmatches(Cadata dat, char **argv)
     /* ms: "match string" - string to use as completion.
      * Overloaded at one place as a temporary. */
     char *s, *ms, *lipre = NULL, *lisuf = NULL, *lpre = NULL, *lsuf = NULL;
-    char **aign = NULL, **dparr = NULL, *oaq = autoq, *oppre = dat->ppre;
+    char **aign = NULL, ***dparr = NULL, *oaq = autoq, *oppre = dat->ppre;
     char *oqp = qipre, *oqs = qisuf, qc, **disp = NULL, *ibuf = NULL;
     char **arrays = NULL;
-    int lpl, lsl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0;
+    int dind, lpl, lsl, bcp = 0, bcs = 0, bpadd = 0, bsadd = 0;
     int ppl = 0, psl = 0, ilen = 0;
     int llpl = 0, llsl = 0, nm = mnum, gflags = 0, ohp = haspattern;
     int isexact, doadd, ois = instring, oib = inbackt;
@@ -2092,7 +2084,7 @@ addmatches(Cadata dat, char **argv)
     struct cmlist mst;
     Cmlist oms = mstack;
     Patprog cp = NULL, *pign = NULL;
-    LinkList aparl = NULL, oparl = NULL, dparl = NULL;
+    LinkList aparl = NULL, oparl = NULL, *dparl = NULL;
     Brinfo bp, bpl = brbeg, obpl, bsl = brend, obsl;
     Heap oldheap;
 
@@ -2120,7 +2112,7 @@ addmatches(Cadata dat, char **argv)
             curexpl->always = !!dat->mesg;
             curexpl->count = curexpl->fcount = 0;
             curexpl->str = dupstring(dat->mesg ? dat->mesg : dat->exp);
-            if (dat->mesg)
+            if (dat->mesg && !dat->dpar && !dat->opar && !dat->apar)
                 addexpl(1);
         } else
             curexpl = NULL;
@@ -2186,11 +2178,24 @@ addmatches(Cadata dat, char **argv)
 	if (dat->opar)
 	    oparl = newlinklist();
 	if (dat->dpar) {
-	    if (*(dat->dpar) == '(')
-		dparr = NULL;
-	    else if ((dparr = get_user_var(dat->dpar)) && !*dparr)
-		dparr = NULL;
-	    dparl = newlinklist();
+	    int darr = 0, dparlen = arrlen(dat->dpar);
+	    char **tail = dat->dpar + dparlen;
+
+	    dparr = (char ***)hcalloc((1 + dparlen) * sizeof(char **));
+	    dparl = (LinkList *)hcalloc((1 + dparlen) * sizeof(LinkList));
+	    queue_signals();
+	    while (darr < dparlen) {
+		if ((dparr[darr] = getaparam(dat->dpar[darr])) && *dparr[darr]) {
+		    dparr[darr] = arrdup(dparr[darr]);
+		    dparl[darr++] = newlinklist();
+		} else {
+		    /* swap in the last -D argument if we didn't get a non-empty array */
+		    dat->dpar[darr] = *--tail;
+		    *tail = NULL;
+		    --dparlen;
+	        }
+	    }
+	    unqueue_signals();
 	}
 	/* Store the matcher in our stack of matchers. */
 	if (dat->match) {
@@ -2244,8 +2249,9 @@ addmatches(Cadata dat, char **argv)
 	    llpl = strlen(lpre);
 	    llsl = strlen(lsuf);
 
-	    if (llpl + (int)strlen(compqiprefix) + (int)strlen(lipre) != origlpre
-	     || llsl + (int)strlen(compqisuffix) + (int)strlen(lisuf) != origlsuf)
+	    /* This used to reference compqiprefix and compqisuffix, why? */
+	    if (llpl + (int)strlen(qipre) + (int)strlen(lipre) != origlpre
+	     || llsl + (int)strlen(qisuf) + (int)strlen(lisuf) != origlsuf)
 		lenchanged = 1;
 
 	    /* Test if there is an existing -P prefix. */
@@ -2507,8 +2513,10 @@ addmatches(Cadata dat, char **argv)
 		}
 		if (!addit) {
 		    compignored++;
-		    if (dparr && !*++dparr)
-			dparr = NULL;
+		    for (dind = 0; dparl && dparl[dind]; dind++) {
+			if (dparr[dind] && !*++dparr[dind])
+			    dparr[dind] = NULL;
+		    }
 		    goto next_array;
 		}
 	    }
@@ -2525,8 +2533,10 @@ addmatches(Cadata dat, char **argv)
 					   !(dat->flags & CMF_FILE) ? 1 : 2) : 0),
 					 &bpl, bcp, &bsl, bcs,
 					 &isexact))) {
-		if (dparr && !*++dparr)
-		    dparr = NULL;
+		for (dind = 0; dparl && dparl[dind]; dind++) {
+		    if (dparr[dind] && !*++dparr[dind])
+			dparr[dind] = NULL;
+		}
 		goto next_array;
 	    }
 	    if (doadd) {
@@ -2553,10 +2563,14 @@ addmatches(Cadata dat, char **argv)
 		    addlinknode(aparl, ms);
 		if (dat->opar)
 		    addlinknode(oparl, s);
-		if (dat->dpar && dparr) {
-		    addlinknode(dparl, *dparr);
-		    if (!*++dparr)
-			dparr = NULL;
+		if (dat->dpar) {
+		    for (dind = 0; dparl[dind]; dind++) {
+			if (dparr[dind]) {
+			    addlinknode(dparl[dind], *dparr[dind]);
+			    if (!*++dparr[dind])
+				dparr[dind] = NULL;
+			}
+		    }
 		}
 		free_cline(lc);
 	    }
@@ -2584,8 +2598,10 @@ addmatches(Cadata dat, char **argv)
 	    set_list_array(dat->apar, aparl);
 	if (dat->opar)
 	    set_list_array(dat->opar, oparl);
-	if (dat->dpar)
-	    set_list_array(dat->dpar, dparl);
+	if (dat->dpar) {
+	    for (dind = 0; dparl[dind]; dind++)
+		set_list_array(dat->dpar[dind], dparl[dind]);
+	}
 	if (dat->exp)
 	    addexpl(0);
 	if (!hasallmatch && (dat->aflags & CAF_ALL)) {
@@ -2883,9 +2899,9 @@ add_match_data(int alt, char *str, char *orig, Cline line,
 		*t++ = '$';
 		*t++ = '\'';
 		*t++ = '\\';
-		*t++ = '0' + ((STOUC(curchar) >> 6) & 7);
-		*t++ = '0' + ((STOUC(curchar) >> 3) & 7);
-		*t++ = '0' + (STOUC(curchar) & 7);
+		*t++ = '0' + (((unsigned char) curchar >> 6) & 7);
+		*t++ = '0' + (((unsigned char) curchar >> 3) & 7);
+		*t++ = '0' + ((unsigned char) curchar & 7);
 		*t++ = '\'';
 	    } while (cnt == MB_INCOMPLETE && fs < fe);
 	    /* Scanning restarts from the spot after the char we skipped. */
@@ -3232,17 +3248,20 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp)
 	    }
 	    *cp = NULL;
 	}
-    } else {
+    } else if (n > 0) {
 	if (!(flags & CGF_NOSORT)) {
 	    /* Now sort the array (it contains matches). */
 	    matchorder = flags;
 	    qsort((void *) rp, n, sizeof(Cmatch),
-		  (int (*) _((const void *, const void *)))matchcmp);
+		  (int (*) (const void *, const void *))matchcmp);
 
+	    /* since the matches are sorted and the default is to remove
+	     * all duplicates, -1 (remove only consecutive dupes) is a no-op,
+	     * so this condition only checks for -2 */
 	    if (!(flags & CGF_UNIQCON)) {
 		int dup;
 
-		/* And delete the ones that occur more than once. */
+		/* we did not pass -2 so go ahead and remove those dupes */
 		for (ap = cp = rp; *ap; ap++) {
 		    *cp++ = *ap;
 		    for (bp = ap; bp[1] && matcheq(*ap, bp[1]); bp++, n--);
@@ -3264,30 +3283,47 @@ makearray(LinkList l, int type, int flags, int *np, int *nlp, int *llp)
 		if ((*ap)->flags & (CMF_NOLIST | CMF_MULT))
 		    nl++;
 	    }
+	/* used -O nosort or -V, don't sort */
 	} else {
+	    /* didn't use -1 or -2, so remove all duplicates (efficient) */
 	    if (!(flags & CGF_UNIQALL) && !(flags & CGF_UNIQCON)) {
-                int dup;
-
-		for (ap = rp; *ap; ap++) {
-		    for (bp = cp = ap + 1; *bp; bp++) {
-			if (!matcheq(*ap, *bp))
-			    *cp++ = *bp;
-			else
+                int dup, del = 0;
+
+		/* To avoid O(n^2) here, sort a copy of the list, then remove marked elements */
+		matchorder = flags;
+		Cmatch *sp, *asp;
+		sp = (Cmatch *) zhalloc((n + 1) * sizeof(Cmatch));
+		memcpy(sp, rp, (n + 1) * sizeof(Cmatch));
+		qsort((void *) sp, n, sizeof(Cmatch),
+		      (int (*) (const void *, const void *))matchcmp);
+		for (asp = sp + 1; *asp; asp++) {
+		    Cmatch *ap = asp - 1, *bp = asp;
+		    if (matcheq(*ap, *bp)) {
+			bp[0]->flags = CMF_DELETE;
+			del = 1;
+		    } else if (!ap[0]->disp) {
+			/* Mark those, that would show the same string in the list. */
+			for (dup = 0; bp[0] && !(bp[0])->disp &&
+				 !strcmp((*ap)->str, (bp[0])->str); bp = ++sp) {
+			    (bp[0])->flags |= CMF_MULT;
+			    dup = 1;
+			}
+			if (dup)
+			    (*ap)->flags |= CMF_FMULT;
+		    }
+		}
+		if (del) {
+		    int n_orig = n;
+		    for (bp = rp, ap = rp; bp < rp + n_orig; ap++, bp++) {
+			while (bp < rp + n_orig && (bp[0]->flags & CMF_DELETE)) {
+			    bp++;
 			    n--;
+			}
+			*ap = *bp;
 		    }
-		    *cp = NULL;
-                    if (!(*ap)->disp) {
-                        for (dup = 0, bp = ap + 1; *bp; bp++)
-                            if (!(*bp)->disp &&
-                                !((*bp)->flags & CMF_MULT) &&
-                                !strcmp((*ap)->str, (*bp)->str)) {
-                                (*bp)->flags |= CMF_MULT;
-                                dup = 1;
-                            }
-                        if (dup)
-                            (*ap)->flags |= CMF_FMULT;
-                    }
+		    *ap = NULL;
 		}
+	    /* passed -1 but not -2, so remove consecutive duplicates (efficient) */
 	    } else if (!(flags & CGF_UNIQCON)) {
 		int dup;