summaryrefslogtreecommitdiff
path: root/do/match
diff options
context:
space:
mode:
Diffstat (limited to 'do/match')
-rw-r--r--do/match288
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;
+}
+