From 997ea719e4c6bed440801ad7b56d8e5c78901ee4 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Wed, 6 Jul 2005 10:06:42 +0000 Subject: 21402: Fix crash with case-insensitive matching. --- ChangeLog | 7 + Src/Zle/compmatch.c | 503 ++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 395 insertions(+), 115 deletions(-) diff --git a/ChangeLog b/ChangeLog index 849594db0..b1821cc0c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2005-07-06 Peter Stephenson + + * 21402: Src/Zle/compmatch.c: Fix crash completing the set + of files AIWebKitMessageViewController.m, + AIWebKitMessageViewPlugin.m, AIWebkitMessageViewStyle.m + with case-insensitive matching. + 2005-06-27 Peter Stephenson * 21387: Doc/Zsh/contrib.yo: document the precision features diff --git a/Src/Zle/compmatch.c b/Src/Zle/compmatch.c index e4babe628..7054feb6d 100644 --- a/Src/Zle/compmatch.c +++ b/Src/Zle/compmatch.c @@ -57,11 +57,9 @@ cmp_cmatchers(Cmatcher a, Cmatcher b) a->llen == b->llen && a->wlen == b->wlen && (!a->llen || cmp_cpatterns(a->line, b->line)) && (a->wlen <= 0 || cmp_cpatterns(a->word, b->word)) && - (!(a->flags & CMF_LEFT) || - (a->lalen == b->lalen && - (!a->lalen || cmp_cpatterns(a->left, b->left)))) && - (!(a->flags & CMF_RIGHT) || - (a->ralen == b->ralen && + (!(a->flags & (CMF_LEFT | CMF_RIGHT)) || + (a->lalen == b->lalen && a->ralen == b->ralen && + (!a->lalen || cmp_cpatterns(a->left, b->left)) && (!a->ralen || cmp_cpatterns(a->right, b->right)))))); } @@ -134,6 +132,7 @@ get_cline(char *l, int ll, char *w, int wl, char *o, int ol, int fl) r->slen = 0; r->flags = fl; r->prefix = r->suffix = NULL; + r->min = r->max = 0; return r; } @@ -212,9 +211,9 @@ void cline_setlens(Cline l, int both) { while (l) { - l->max = cline_sublen(l); + l->min = cline_sublen(l); if (both) - l->min = l->max; + l->max = l->min; l = l->next; } } @@ -342,7 +341,7 @@ add_match_part(Cmatcher m, char *l, char *w, int wl, /* If the anchors are equal, we keep only one. */ - if (!strncmp(l, w, wl)) + if (l && !strncmp(l, w, wl)) l = NULL; /* Split the new part into parts and turn the last one into a @@ -350,7 +349,6 @@ add_match_part(Cmatcher m, char *l, char *w, int wl, p = bld_parts(s, sl, osl, &lp); - p->flags &= ~CLF_NEW; if (m && (m->flags & CMF_LEFT)) { lp->flags |= CLF_SUF; lp->suffix = lp->prefix; @@ -380,10 +378,16 @@ add_match_part(Cmatcher m, char *l, char *w, int wl, matchsubs = matchlastsub = NULL; } /* Store the arguments in the last part-cline. */ - lp->line = l; lp->llen = wl; - lp->word = w; lp->wlen = wl; - lp->orig = o; lp->olen = ol; - lp->flags &= ~CLF_NEW; + if (lp->llen || lp->wlen) { + lp->next = get_cline(l, wl, w, wl, o, ol, CLF_NEW); + lp = lp->next; + } else { + lp->line = l; lp->llen = wl; + lp->word = w; lp->wlen = wl; + lp->orig = o; lp->olen = ol; + } + if (o || ol) + lp->flags &= ~CLF_NEW; /* Finally, put the new parts on the list. */ if (matchlastpart) @@ -412,12 +416,32 @@ add_match_sub(Cmatcher m, char *l, int ll, char *w, int wl) /* And add the cline. */ if (wl || ll) { - n = get_cline(l, ll, w, wl, NULL, 0, flags); - if (matchlastsub) - matchlastsub->next = n; - else - matchsubs = n; - matchlastsub = n; + Cline p, lp; + + if ((p = n = bld_parts(w, wl, ll, &lp)) && n != lp) { + for (; p->next != lp; p = p->next); + + if (matchsubs) { + matchlastsub->next = n->prefix; + n->prefix = matchsubs; + } + matchsubs = matchlastsub = lp; + + if (matchlastpart) + matchlastpart->next = n; + else + matchparts = n; + p->next = 0; + matchlastpart = p; + } else { + n = get_cline(l, ll, w, wl, NULL, 0, + flags | ((m && m->wlen == -2) ? CLF_SKIP : 0)); + if (matchlastsub) + matchlastsub->next = n; + else + matchsubs = n; + matchlastsub = n; + } } } @@ -435,9 +459,9 @@ int match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, int sfx, int test, int part) { - int ll = strlen(l), lw = strlen(w), oll = ll, olw = lw; + int ll = strlen(l), lw = strlen(w), oll = ll, olw = lw, exact = 0, wexact = 0; int il = 0, iw = 0, t, ind, add, he = 0, bpc, obc = bc, bslash; - VARARR(unsigned char, ea, ll + 1); + VARARR(unsigned char, ea, (ll > lw ? ll : lw) + 1); char *ow; Cmlist ms; Cmatcher mp, lm = NULL; @@ -467,8 +491,56 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, bp->curpos = bc; bp = bp->next; } - while (ll && lw) { - /* First try the matchers. */ + /*** This once was: `while (ll && lw)', but then ignored characters at + * the end were not, well, ignored. */ + while (ll) { + + /* Hm, we unconditionally first tried the matchers for the cases + * where the beginnings of the line and word patterns match the + * same character(s). + * But first testing if the characters are the same is sooo + * much faster... + * Maybe it's OK to make same-character matching be preferred in + * recursive calls. At least, it /seems/ to work. + * + * Let's try. + * + * Update: this once tested `test && ...' to check for exact + * character matches only in recursive calls. But then one + * can't complete `nom' to `nomatch' with a match spec + * of `B:[nN][oO]=' because that will eat the `no'. + * But that would break completion of strings like `nonomatch' + * because the `B:[nN][oO]=' doesn't match the second `no'. + * For this we added the code below that can remove already + * accepted exact characters and try again, preferring match + * specs. + */ + + bslash = 0; + if (!sfx && lw && (!part || test) && + (l[ind] == w[ind] || + (bslash = (lw > 1 && w[ind] == '\\' && + (ind ? (w[0] == l[0]) : (w[1] == l[0])))))) { + /* No matcher could be used, but the strings have the same + * character here, skip over it. */ + l += add; w += (bslash ? (add + add) : add); + il++; iw += 1 + bslash; + ll--; lw -= 1 + bslash; + bc++; + exact++; + wexact += 1 + bslash; + if (!test) + while (bp && bc >= (useqbr ? bp->qpos : bp->pos)) { + bp->curpos = matchbufadded + (sfx ? (ow - w) : (w - ow)) + obc; + bp = bp->next; + } + lm = NULL; + he = 0; + + continue; + } + retry: + /* First try the matchers. Err... see above. */ for (mp = NULL, ms = mstack; !mp && ms; ms = ms->next) { for (mp = ms->matcher; mp; mp = mp->next) { t = 1; @@ -481,29 +553,32 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, continue; if (mp->wlen < 0) { - int both, loff, aoff, llen, alen, zoff, moff, ct, ict; + int both, loff, aoff, llen, alen, zoff, moff, ct, ict, aol; char *tp, savl = '\0', savw; - Cpattern ap; + Cpattern ap, aop; /* This is for `*' patterns, first initialise some * local variables. */ llen = mp->llen; - alen = (mp->flags & CMF_LEFT ? mp->lalen : mp->ralen); - + if (mp->flags & CMF_LEFT) { + alen = mp->lalen; aol = mp->ralen; + } else { + alen = mp->ralen; aol = mp->lalen; + } /* Give up if we don't have enough characters for the * line-string and the anchor. */ if (ll < llen + alen || lw < alen) continue; if (mp->flags & CMF_LEFT) { - ap = mp->left; zoff = 0; moff = alen; + ap = mp->left; zoff = 0; moff = alen; aop = mp->right; if (sfx) { both = 0; loff = -llen; aoff = -(llen + alen); } else { both = 1; loff = alen; aoff = 0; } } else { - ap = mp->right; zoff = alen; moff = 0; + ap = mp->right; zoff = alen; moff = 0; aop = mp->left; if (sfx) { both = 1; loff = -(llen + alen); aoff = -alen; } else { @@ -515,34 +590,49 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, continue; if (ap) { if (!pattern_match(ap, l + aoff, NULL, NULL) || - (both && (!pattern_match(ap, w + aoff, NULL, NULL) || - !match_parts(l + aoff, w + aoff, alen, - part)))) + (both && + (!pattern_match(ap, w + aoff, NULL, NULL) || + (aol && aol <= aoff + iw && + !pattern_match(aop, w + aoff - aol, + NULL, NULL)) || + !match_parts(l + aoff, w + aoff, alen, part)))) continue; - } else if (!both || il || iw) + } else if (!both || ((mp->flags & CMF_INTER) ? + ((mp->flags & CMF_LINE) ? iw : il) : + (il || iw))) continue; /* Fine, now we call ourselves recursively to find the * string matched by the `*'. */ - if (sfx) { - savl = l[-(llen + zoff)]; + if (sfx && (savl = l[-(llen + zoff)])) l[-(llen + zoff)] = '\0'; - } for (t = 0, tp = w, ct = 0, ict = lw - alen + 1; ict; tp += add, ct++, ict--) { if ((both && (!ap || !test || - !pattern_match(ap, tp + aoff, NULL, NULL))) || + !pattern_match(ap, tp + aoff, NULL, NULL) || + (aol && aol <= aoff + ct + iw && + !pattern_match(aop, tp + aoff - aol, + NULL, NULL)))) || (!both && pattern_match(ap, tp - moff, NULL, NULL) && - match_parts(l + aoff , tp - moff, alen, part))) { + (!aol || (aol <= iw + ct - moff && + pattern_match(aop, tp - moff - aol, + NULL, NULL))) && + (mp->wlen == -1 || + match_parts(l + aoff , tp - moff, + alen, part)))) { + if (!both && mp->wlen == -1 && + !match_parts(l + aoff , tp - moff, alen, part)) + break; if (sfx) { - savw = tp[-zoff]; - tp[-zoff] = '\0'; + if ((savw = tp[-zoff])) + tp[-zoff] = '\0'; t = match_str(l - ll, w - lw, NULL, 0, NULL, 1, 2, part); - tp[-zoff] = savw; + if (savw) + tp[-zoff] = savw; } else t = match_str(l + llen + moff, tp + moff, NULL, 0, NULL, 0, 1, part); @@ -551,7 +641,7 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, } } ict = ct; - if (sfx) + if (sfx && savl) l[-(llen + zoff)] = savl; /* Have we found a position in w where the rest of l @@ -620,6 +710,7 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, ll -= llen; il += llen; lw -= alen; iw += alen; bc += llen; + exact = 0; if (!test) while (bp && @@ -666,30 +757,42 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, } if (mp->flags & CMF_LEFT) { /* Try to match the left anchor, if any. */ - if (til < mp->lalen || tiw < mp->lalen) + if (til < mp->lalen || tiw < mp->lalen + mp->ralen) continue; else if (mp->left) t = pattern_match(mp->left, tl - mp->lalen, NULL, NULL) && pattern_match(mp->left, tw - mp->lalen, - NULL, NULL); + NULL, NULL) && + (!mp->ralen || + pattern_match(mp->right, + tw - mp->lalen - mp->ralen, + NULL, NULL)); else - t = (!sfx && !il && !iw); + t = (!sfx && !((mp->flags & CMF_INTER) ? + ((mp->flags & CMF_LINE) ? iw : il) : + (il || iw))); } if (mp->flags & CMF_RIGHT) { /* Try to match the right anchor, if any. */ if (tll < mp->llen + mp->ralen || - tlw < mp->wlen + mp->ralen) + tlw < mp->wlen + mp->ralen + mp->lalen) continue; - else if (mp->left) + else if (mp->right) t = pattern_match(mp->right, tl + mp->llen - mp->ralen, NULL, NULL) && pattern_match(mp->right, tw + mp->wlen - mp->ralen, - NULL, NULL); + NULL, NULL) && + (!mp->lalen || + pattern_match(mp->left, tw + mp->wlen - + mp->ralen - mp->lalen, + NULL, NULL)); else - t = (sfx && !il && !iw); + t = (sfx && !((mp->flags & CMF_INTER) ? + ((mp->flags & CMF_LINE) ? iw : il) : + (il || iw))); } /* Now try to match the line and word patterns. */ if (!t || @@ -700,15 +803,26 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, /* Probably add the matched strings. */ if (!test) { if (sfx) - add_match_str(NULL, NULL, w, ow - w, 0); + { + if (ow >= w) + add_match_str(NULL, NULL, w, ow - w, sfx); + } else - add_match_str(NULL, NULL, ow, w - ow, 0); - add_match_str(mp, tl, tw, mp->wlen, 0); + { + if (w >= ow) + add_match_str(NULL, NULL, ow, w - ow, sfx); + } + add_match_str(mp, tl, tw, mp->wlen, sfx); if (sfx) - add_match_sub(NULL, NULL, 0, w, ow - w); + { + if (ow >= w) + add_match_sub(NULL, NULL, 0, w, ow - w); + } else - add_match_sub(NULL, NULL, 0, ow, w - ow); - + { + if (w >= ow) + add_match_sub(NULL, NULL, 0, ow, w - ow); + } add_match_sub(mp, tl, mp->llen, tw, mp->wlen); } if (sfx) { @@ -719,6 +833,7 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, il += mp->llen; iw += mp->wlen; ll -= mp->llen; lw -= mp->wlen; bc += mp->llen; + exact = 0; if (!test) while (bp && @@ -736,10 +851,13 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, if (mp) continue; + /* Same code as at the beginning, used in top-level calls. */ + bslash = 0; - if (l[ind] == w[ind] || - (bslash = (lw > 1 && w[ind] == '\\' && - (ind ? (w[0] == l[0]) : (w[1] == l[0]))))) { + if ((!test || sfx) && lw && + (l[ind] == w[ind] || + (bslash = (lw > 1 && w[ind] == '\\' && + (ind ? (w[0] == l[0]) : (w[1] == l[0])))))) { /* No matcher could be used, but the strings have the same * character here, skip over it. */ l += add; w += (bslash ? (add + add ) : add); @@ -754,6 +872,25 @@ match_str(char *l, char *w, Brinfo *bpp, int bc, int *rwlp, lm = NULL; he = 0; } else { + + if (!lw) + break; + + if (exact && !part) { + /* If we just accepted some characters directly (at the + * beginning of the loop) and now can't match any further, + * we go back to before those characters and try again, + * preferring match specs this time. */ + + il -= exact; iw -= wexact; + ll += exact; lw += wexact; + bc -= exact; + l -= add * exact; w -= add * wexact; + + exact = wexact = 0; + + goto retry; + } /* No matcher and different characters: l does not match w. */ if (test) return 0; @@ -816,10 +953,15 @@ match_parts(char *l, char *w, int n, int part) char lsav = l[n], wsav = w[n]; int ret; - l[n] = w[n] = '\0'; + if (lsav) + l[n] = '\0'; + if (wsav) + w[n] = '\0'; ret = match_str(l, w, NULL, 0, NULL, 0, 1, part); - l[n] = lsav; - w[n] = wsav; + if (lsav) + l[n] = lsav; + if (wsav) + w[n] = wsav; return ret; } @@ -955,7 +1097,7 @@ comp_match(char *pfx, char *sfx, char *w, Patprog cp, Cline *clp, int qu, * corresponding character. */ /**/ -static int +mod_export int pattern_match(Cpattern p, char *s, unsigned char *in, unsigned char *out) { unsigned char c; @@ -999,25 +1141,28 @@ pattern_match(Cpattern p, char *s, unsigned char *in, unsigned char *out) Cline bld_parts(char *str, int len, int plen, Cline *lp) { - Cline ret = NULL, *q = &ret, n; + Cline ret = NULL, *q = &ret, n = NULL; Cmlist ms; Cmatcher mp; int t, op = plen; - char *p = str; + char *p = str, *os = str; while (len) { for (t = 0, ms = bmatchers; ms && !t; ms = ms->next) { mp = ms->matcher; - if (mp && mp->flags == CMF_RIGHT && mp->wlen < 0 && - !mp->llen && len >= mp->ralen && mp->ralen && - pattern_match(mp->right, str, NULL, NULL)) { + if (mp && mp->flags == CMF_RIGHT && mp->wlen < 0 && mp->ralen && + !mp->llen && len >= mp->ralen && (str - os) >= mp->lalen && + pattern_match(mp->right, str, NULL, NULL) && + (!mp->lalen || + ((str - os) >= mp->lalen && + pattern_match(mp->left, str - mp->lalen, NULL, NULL)))) { int olen = str - p, llen; /* We found an anchor, create a new cline. The NEW flag * is set if the characters before the anchor were not * on the line. */ *q = n = get_cline(NULL, mp->ralen, str, mp->ralen, NULL, 0, - ((plen < 0) ? CLF_NEW : 0)); + ((plen <= 0) ? CLF_NEW : 0)); /* If there were any characters before the anchor, add * them as a cline struct. */ @@ -1045,14 +1190,18 @@ bld_parts(char *str, int len, int plen, Cline *lp) } /* This is the cline struct for the remaining string at the end. */ - *q = n = get_cline(NULL, 0, NULL, 0, NULL, 0, (plen < 0 ? CLF_NEW : 0)); if (p != str) { int olen = str - p, llen = (op < 0 ? 0 : op); + *q = n = get_cline(NULL, 0, NULL, 0, NULL, 0, (plen <= 0 ? CLF_NEW : 0)); + if (llen > olen) llen = olen; n->prefix = get_cline(NULL, llen, p, olen, NULL, 0, 0); } + else if (!ret) + *q = n = get_cline(NULL, 0, NULL, 0, NULL, 0, (plen <= 0 ? CLF_NEW : 0)); + n->next = NULL; if (lp) @@ -1261,7 +1410,7 @@ cmp_anchors(Cline o, Cline n, int join) if (line) { o->flags |= CLF_LINE; o->word = NULL; - n->wlen = 0; + o->wlen = 0; } return 1; } @@ -1447,10 +1596,24 @@ sub_match(Cmdata md, char *str, int len, int sfx) if (check_cmdata(md, sfx)) return ret; + /* + * Look for a common prefix. If we do include metafied + * characters, at this stage we still need the overall length + * including Meta's as separate characters. + */ for (l = 0, p = str, q = md->str; l < len && l < md->len && p[ind] == q[ind]; - l++, p += add, q += add); + l++, p += add, q += add) {} + /* Make sure we don't end in the middle of a Meta sequence. */ + if (add == 1) { + if (l && p[-1] == Meta) + l--; + } else { + if (l && ((l < len && p[-1] == Meta) + || (l < md->len && q[-1] == Meta))) + l--; + } if (l) { /* There was a common prefix, use it. */ md->len -= l; len -= l; @@ -1494,6 +1657,8 @@ join_psfx(Cline ot, Cline nt, Cline *orest, Cline *nrest, int sfx) *orest = NULL; if (nrest) *nrest = n; + if (n && n->wlen) + ot->flags |= CLF_MISS; return; } @@ -1531,6 +1696,7 @@ join_psfx(Cline ot, Cline nt, Cline *orest, Cline *nrest, int sfx) continue; } + o->llen = o->llen - ot->slen; join = 1; line = 0; slen = &(o->wlen); sstr = &(o->word); } if (join) { @@ -1676,7 +1842,7 @@ join_mid(Cline o, Cline n) * didn't. */ /**/ -static void +static int sub_join(Cline a, Cline b, Cline e, int anew) { if (!e->suffix && a->prefix) { @@ -1699,31 +1865,34 @@ sub_join(Cline a, Cline b, Cline e, int anew) *p = e->prefix; ca = a->prefix; - while (n != op) { + while (n) { e->prefix = cp_cline(n, 0); a->prefix = cp_cline(ca, 0); if (anew) { + int f = e->flags; + join_psfx(e, a, NULL, NULL, 0); - if (e->prefix) { - e->min += min; - e->max += max; - break; - } + e->flags = f; + if (e->prefix) + return max - min; } else { - join_psfx(e, a, NULL, NULL, 0); - if (a->prefix) { - a->min += min; - a->max += max; - break; - } + int f = e->flags; + + join_psfx(a, e, NULL, NULL, 0); + e->flags = f; + if (a->prefix) + return max - min; } min -= n->min; - max -= n->max; + if (n == op) + break; n = n->next; } + return max - min; } + return 0; } /* This simplifies the cline list given as the first argument so that @@ -1740,7 +1909,8 @@ join_clines(Cline o, Cline n) if (!o) return n; else { - Cline oo = o, nn = n, po = NULL, pn = NULL; + Cline oo = o, nn = n, po = NULL, pn = NULL, x; + int diff; /* Walk through the lists. */ while (o && n) { @@ -1750,30 +1920,52 @@ join_clines(Cline o, Cline n) if ((o->flags & CLF_NEW) && !(n->flags & CLF_NEW)) { Cline t, tn; - for (t = o; (tn = t->next) && (tn->flags & CLF_NEW); t = tn); - if (tn && cmp_anchors(tn, n, 0)) { - sub_join(n, o, tn, 1); + for (t = o; (tn = t->next) && + ((tn->flags & CLF_NEW) || !cmp_anchors(tn, n, 0)); + t = tn); + if (tn) { + diff = sub_join(n, o, tn, 1); if (po) po->next = tn; else oo = tn; + t->next = NULL; free_cline(o); + x = o; o = tn; - o->flags |= CLF_MISS; + + if (po && po->prefix && cmp_anchors(x, po, 0)) { + po->flags |= CLF_MISS; + po->max += diff; + } else { + o->flags |= CLF_MISS; + o->max += diff; + } continue; } } if (!(o->flags & CLF_NEW) && (n->flags & CLF_NEW)) { Cline t, tn; - for (t = n; (tn = t->next) && (tn->flags & CLF_NEW); t = tn); - if (tn && cmp_anchors(o, tn, 0)) { - sub_join(o, n, tn, 0); + for (t = n; (tn = t->next) && + ((tn->flags & CLF_NEW) || !cmp_anchors(o, tn, 0)); + t = tn); + if (tn) { + int of = o->flags & CLF_MISS; + + diff = sub_join(o, n, tn, 0); + o->flags = (o->flags & ~CLF_MISS) | of; + if (po && po->prefix && cmp_anchors(n, pn, 0)) { + po->flags |= CLF_MISS; + po->max += diff; + } else { + o->flags |= CLF_MISS; + o->max += diff; + } n = tn; - o->flags |= CLF_MISS; continue; } } @@ -1801,6 +1993,7 @@ join_clines(Cline o, Cline n) t = tn); if (tn && cmp_anchors(tn, n, 1)) { sub_join(n, o, tn, 1); + if (po) po->next = tn; else @@ -1824,39 +2017,120 @@ 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)) { - Cline t, tn; - - for (t = n; (tn = t->next) && !cmp_anchors(o, tn, 1); t = tn); + Cline t, tn, tt, to = NULL; + for (t = n; (tn = t->next); t = tn) + if (!(tn->flags & CLF_NEW) && (tn->flags & CLF_SKIP)) { + for (tt = o; (to = tt->next); tt = to) + if (!(to->flags & CLF_NEW) && (to->flags & CLF_SKIP) && + cmp_anchors(tn, to, 1)) + break; + if (to) + break; + } if (tn) { - sub_join(o, n, tn, 0); + if (po) + po->next = to; + else + oo = to; + o = to; + + diff = sub_join(o, n, tn, 0); - n = tn; o->flags |= CLF_MISS; + o->max += diff; + + n = tn; + po = o; + o = o->next; + pn = n; + n = n->next; continue; } else { - for (t = o; (tn = t->next) && !cmp_anchors(n, tn, 1); - t = tn); + for (t = o; (to = t->next); t = to) + if ((to->flags & CLF_SKIP) && cmp_anchors(n, to, 1)) + break; - if (tn) { - sub_join(n, o, tn, 1); + if (to) { + diff = sub_join(n, o, to, 1); if (po) - po->next = tn; + po->next = to; else - oo = tn; - o = tn; - o->flags |= CLF_MISS; + oo = to; + x = o; + o = to; + if (po && po->prefix && cmp_anchors(x, po, 0)) { + po->flags |= CLF_MISS; + po->max += diff; + } else { + o->flags |= CLF_MISS; + o->max += diff; + } continue; } else { - if (o->flags & CLF_SUF) - break; + for (tt = NULL, t = n; (tn = t->next); t = tn) { + if (tn->flags & CLF_SKIP) + for (tt = o; (to = tt->next); tt = to) + if ((to->flags & CLF_SKIP) && + cmp_anchors(tn, to, 1)) + break; + if (to) + break; + } + if (to) { + diff = sub_join(n, o, to, 1); + + if (po) + po->next = to; + else + oo = to; + x = o; + o = to; + if (po && po->prefix && cmp_anchors(x, po, 0)) { + po->flags |= CLF_MISS; + po->max += diff; + } else { + o->flags |= CLF_MISS; + o->max += diff; + } + continue; + } else { + for (tn = n; tn; tn = tn->next) + if ((tn->flags & CLF_NEW) == + (o->flags & CLF_NEW) && + cmp_anchors(tn, o, 1)) break; + + if (tn) { + int of = o->flags & CLF_MISS; + + if ((diff = sub_join(o, n, tn, 0))) { + o->flags = (o->flags & ~CLF_MISS) | of; + if (po && po->prefix) { + po->flags |= CLF_MISS; + po->max += diff; + } + else { + o->flags |= CLF_MISS; + o->max += diff; + } + } + n = tn; + po = o; + o = o->next; + pn = n; + n = n->next; + continue; + } + if (o->flags & CLF_SUF) + break; - o->word = o->line = o->orig = NULL; - o->wlen = 0; - free_cline(o->next); - o->next = NULL; - o->flags |= CLF_MISS; + o->word = o->line = o->orig = NULL; + o->wlen = 0; + free_cline(o->next); + o->next = NULL; + o->flags |= CLF_MISS; + } } } } @@ -1895,4 +2169,3 @@ join_clines(Cline o, Cline n) return oo; } } - -- cgit 1.4.1