diff options
Diffstat (limited to 'do/match')
-rw-r--r-- | do/match | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/do/match b/do/match new file mode 100644 index 0000000000..99197762f0 --- /dev/null +++ b/do/match @@ -0,0 +1,288 @@ +int +do_match(TARG,arg,gimme,arglast) +STR *TARG; +register ARG *arg; +int gimme; +int *arglast; +{ + register STR **st = stack->ary_array; + register SPAT *spat = arg[2].arg_ptr.arg_spat; + register char *t; + register int sp = arglast[0] + 1; + STR *srchstr = st[sp]; + register char *s = str_get(st[sp]); + char *strend = s + st[sp]->str_cur; + STR *tmpstr; + char *myhint = hint; + int global; + int safebase; + char *truebase = s; + register REGEXP *rx = spat->spat_regexp; + + hint = Nullch; + if (!spat) { + if (gimme == G_ARRAY) + return --sp; + str_set(TARG,Yes); + STABSET(TARG); + st[sp] = TARG; + return sp; + } + global = spat->spat_flags & SPAT_GLOBAL; + safebase = (gimme == G_ARRAY) || global; + if (!s) + fatal("panic: do_match"); + if (spat->spat_flags & SPAT_USED) { +#ifdef DEBUGGING + if (debug & 8) + deb("2.SPAT USED\n"); +#endif + if (gimme == G_ARRAY) + return --sp; + str_set(TARG,No); + STABSET(TARG); + st[sp] = TARG; + return sp; + } + --sp; + if (spat->spat_runtime) { + nointrp = "|)"; + sp = eval(spat->spat_runtime,G_SCALAR,sp); + st = stack->ary_array; + t = str_get(tmpstr = st[sp--]); + nointrp = ""; +#ifdef DEBUGGING + if (debug & 8) + deb("2.SPAT /%s/\n",t); +#endif + if (!global && rx) + regfree(rx); + spat->spat_regexp = Null(REGEXP*); /* crucial if regcomp aborts */ + spat->spat_regexp = regcomp(t,t+tmpstr->str_cur, + spat->spat_flags & SPAT_FOLD); + if (!spat->spat_regexp->prelen && lastspat) + spat = lastspat; + if (spat->spat_flags & SPAT_KEEP) { + if (!(spat->spat_flags & SPAT_FOLD)) + scanconst(spat,spat->spat_regexp->precomp, + spat->spat_regexp->prelen); + if (spat->spat_runtime) + arg_free(spat->spat_runtime); /* it won't change, so */ + spat->spat_runtime = Nullarg; /* no point compiling again */ + hoistmust(spat); + if (curcmd->c_expr && (curcmd->c_flags & CF_OPTIMIZE) == CFT_EVAL) { + curcmd->c_flags &= ~CF_OPTIMIZE; + opt_arg(curcmd, 1, curcmd->c_type == C_EXPR); + } + } + if (global) { + if (rx) { + if (rx->startp[0]) { + s = rx->endp[0]; + if (s == rx->startp[0]) + s++; + if (s > strend) { + regfree(rx); + rx = spat->spat_regexp; + goto nope; + } + } + regfree(rx); + } + } + else if (!spat->spat_regexp->nparens) + gimme = G_SCALAR; /* accidental array context? */ + rx = spat->spat_regexp; + if (regexec(rx, s, strend, s, 0, + srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr, + safebase)) { + if (rx->subbase || global) + curspat = spat; + lastspat = spat; + goto gotcha; + } + else { + if (gimme == G_ARRAY) + return sp; + str_sset(TARG,&str_no); + STABSET(TARG); + st[++sp] = TARG; + return sp; + } + } + else { +#ifdef DEBUGGING + if (debug & 8) { + char ch; + + if (spat->spat_flags & SPAT_ONCE) + ch = '?'; + else + ch = '/'; + deb("2.SPAT %c%s%c\n",ch,rx->precomp,ch); + } +#endif + if (!rx->prelen && lastspat) { + spat = lastspat; + rx = spat->spat_regexp; + } + t = s; + play_it_again: + if (global && rx->startp[0]) { + t = s = rx->endp[0]; + if (s == rx->startp[0]) + s++,t++; + if (s > strend) + goto nope; + } + if (myhint) { + if (myhint < s || myhint > strend) + fatal("panic: hint in do_match"); + s = myhint; + if (rx->regback >= 0) { + s -= rx->regback; + if (s < t) + s = t; + } + else + s = t; + } + else if (spat->spat_short) { + if (spat->spat_flags & SPAT_SCANFIRST) { + if (srchstr->str_pok & SP_STUDIED) { + if (screamfirst[spat->spat_short->str_rare] < 0) + goto nope; + else if (!(s = screaminstr(srchstr,spat->spat_short))) + goto nope; + else if (spat->spat_flags & SPAT_ALL) + goto yup; + } +#ifndef lint + else if (!(s = fbminstr((unsigned char*)s, + (unsigned char*)strend, spat->spat_short))) + goto nope; +#endif + else if (spat->spat_flags & SPAT_ALL) + goto yup; + if (s && rx->regback >= 0) { + ++spat->spat_short->str_u.str_useful; + s -= rx->regback; + if (s < t) + s = t; + } + else + s = t; + } + else if (!multiline && (*spat->spat_short->str_ptr != *s || + bcmp(spat->spat_short->str_ptr, s, spat->spat_slen) )) + goto nope; + if (--spat->spat_short->str_u.str_useful < 0) { + str_free(spat->spat_short); + spat->spat_short = Nullstr; /* opt is being useless */ + } + } + if (!rx->nparens && !global) { + gimme = G_SCALAR; /* accidental array context? */ + safebase = FALSE; + } + if (regexec(rx, s, strend, truebase, 0, + srchstr->str_pok & SP_STUDIED ? srchstr : Nullstr, + safebase)) { + if (rx->subbase || global) + curspat = spat; + lastspat = spat; + if (spat->spat_flags & SPAT_ONCE) + spat->spat_flags |= SPAT_USED; + goto gotcha; + } + else { + if (global) + rx->startp[0] = Nullch; + if (gimme == G_ARRAY) + return sp; + str_sset(TARG,&str_no); + STABSET(TARG); + st[++sp] = TARG; + return sp; + } + } + /*NOTREACHED*/ + + gotcha: + if (gimme == G_ARRAY) { + int iters, i, len; + + iters = rx->nparens; + if (global && !iters) + i = 1; + else + i = 0; + if (sp + iters + i >= stack->ary_max) { + astore(stack,sp + iters + i, Nullstr); + st = stack->ary_array; /* possibly realloced */ + } + + for (i = !i; i <= iters; i++) { + st[++sp] = str_mortal(&str_no); + /*SUPPRESS 560*/ + if (s = rx->startp[i]) { + len = rx->endp[i] - s; + if (len > 0) + str_nset(st[sp],s,len); + } + } + if (global) { + truebase = rx->subbeg; + goto play_it_again; + } + return sp; + } + else { + str_sset(TARG,&str_yes); + STABSET(TARG); + st[++sp] = TARG; + return sp; + } + +yup: + ++spat->spat_short->str_u.str_useful; + lastspat = spat; + if (spat->spat_flags & SPAT_ONCE) + spat->spat_flags |= SPAT_USED; + if (global) { + rx->subbeg = t; + rx->subend = strend; + rx->startp[0] = s; + rx->endp[0] = s + spat->spat_short->str_cur; + curspat = spat; + goto gotcha; + } + if (sawampersand) { + char *tmps; + + if (rx->subbase) + Safefree(rx->subbase); + tmps = rx->subbase = nsavestr(t,strend-t); + rx->subbeg = tmps; + rx->subend = tmps + (strend-t); + tmps = rx->startp[0] = tmps + (s - t); + rx->endp[0] = tmps + spat->spat_short->str_cur; + curspat = spat; + } + str_sset(TARG,&str_yes); + STABSET(TARG); + st[++sp] = TARG; + return sp; + +nope: + rx->startp[0] = Nullch; + if (spat->spat_short) + ++spat->spat_short->str_u.str_useful; + if (gimme == G_ARRAY) + return sp; + str_sset(TARG,&str_no); + STABSET(TARG); + st[++sp] = TARG; + return sp; +} + |