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; }