1*9880d681SAndroid Build Coastguard Worker/*- 2*9880d681SAndroid Build Coastguard Worker * This code is derived from OpenBSD's libc/regex, original license follows: 3*9880d681SAndroid Build Coastguard Worker * 4*9880d681SAndroid Build Coastguard Worker * Copyright (c) 1992, 1993, 1994 Henry Spencer. 5*9880d681SAndroid Build Coastguard Worker * Copyright (c) 1992, 1993, 1994 6*9880d681SAndroid Build Coastguard Worker * The Regents of the University of California. All rights reserved. 7*9880d681SAndroid Build Coastguard Worker * 8*9880d681SAndroid Build Coastguard Worker * This code is derived from software contributed to Berkeley by 9*9880d681SAndroid Build Coastguard Worker * Henry Spencer. 10*9880d681SAndroid Build Coastguard Worker * 11*9880d681SAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without 12*9880d681SAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions 13*9880d681SAndroid Build Coastguard Worker * are met: 14*9880d681SAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright 15*9880d681SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer. 16*9880d681SAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright 17*9880d681SAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the 18*9880d681SAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution. 19*9880d681SAndroid Build Coastguard Worker * 3. Neither the name of the University nor the names of its contributors 20*9880d681SAndroid Build Coastguard Worker * may be used to endorse or promote products derived from this software 21*9880d681SAndroid Build Coastguard Worker * without specific prior written permission. 22*9880d681SAndroid Build Coastguard Worker * 23*9880d681SAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24*9880d681SAndroid Build Coastguard Worker * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25*9880d681SAndroid Build Coastguard Worker * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26*9880d681SAndroid Build Coastguard Worker * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27*9880d681SAndroid Build Coastguard Worker * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28*9880d681SAndroid Build Coastguard Worker * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29*9880d681SAndroid Build Coastguard Worker * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30*9880d681SAndroid Build Coastguard Worker * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31*9880d681SAndroid Build Coastguard Worker * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32*9880d681SAndroid Build Coastguard Worker * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33*9880d681SAndroid Build Coastguard Worker * SUCH DAMAGE. 34*9880d681SAndroid Build Coastguard Worker * 35*9880d681SAndroid Build Coastguard Worker * @(#)engine.c 8.5 (Berkeley) 3/20/94 36*9880d681SAndroid Build Coastguard Worker */ 37*9880d681SAndroid Build Coastguard Worker 38*9880d681SAndroid Build Coastguard Worker/* 39*9880d681SAndroid Build Coastguard Worker * The matching engine and friends. This file is #included by regexec.c 40*9880d681SAndroid Build Coastguard Worker * after suitable #defines of a variety of macros used herein, so that 41*9880d681SAndroid Build Coastguard Worker * different state representations can be used without duplicating masses 42*9880d681SAndroid Build Coastguard Worker * of code. 43*9880d681SAndroid Build Coastguard Worker */ 44*9880d681SAndroid Build Coastguard Worker 45*9880d681SAndroid Build Coastguard Worker#ifdef SNAMES 46*9880d681SAndroid Build Coastguard Worker#define matcher smatcher 47*9880d681SAndroid Build Coastguard Worker#define fast sfast 48*9880d681SAndroid Build Coastguard Worker#define slow sslow 49*9880d681SAndroid Build Coastguard Worker#define dissect sdissect 50*9880d681SAndroid Build Coastguard Worker#define backref sbackref 51*9880d681SAndroid Build Coastguard Worker#define step sstep 52*9880d681SAndroid Build Coastguard Worker#define print sprint 53*9880d681SAndroid Build Coastguard Worker#define at sat 54*9880d681SAndroid Build Coastguard Worker#define match smat 55*9880d681SAndroid Build Coastguard Worker#define nope snope 56*9880d681SAndroid Build Coastguard Worker#endif 57*9880d681SAndroid Build Coastguard Worker#ifdef LNAMES 58*9880d681SAndroid Build Coastguard Worker#define matcher lmatcher 59*9880d681SAndroid Build Coastguard Worker#define fast lfast 60*9880d681SAndroid Build Coastguard Worker#define slow lslow 61*9880d681SAndroid Build Coastguard Worker#define dissect ldissect 62*9880d681SAndroid Build Coastguard Worker#define backref lbackref 63*9880d681SAndroid Build Coastguard Worker#define step lstep 64*9880d681SAndroid Build Coastguard Worker#define print lprint 65*9880d681SAndroid Build Coastguard Worker#define at lat 66*9880d681SAndroid Build Coastguard Worker#define match lmat 67*9880d681SAndroid Build Coastguard Worker#define nope lnope 68*9880d681SAndroid Build Coastguard Worker#endif 69*9880d681SAndroid Build Coastguard Worker 70*9880d681SAndroid Build Coastguard Worker/* another structure passed up and down to avoid zillions of parameters */ 71*9880d681SAndroid Build Coastguard Workerstruct match { 72*9880d681SAndroid Build Coastguard Worker struct re_guts *g; 73*9880d681SAndroid Build Coastguard Worker int eflags; 74*9880d681SAndroid Build Coastguard Worker llvm_regmatch_t *pmatch; /* [nsub+1] (0 element unused) */ 75*9880d681SAndroid Build Coastguard Worker const char *offp; /* offsets work from here */ 76*9880d681SAndroid Build Coastguard Worker const char *beginp; /* start of string -- virtual NUL precedes */ 77*9880d681SAndroid Build Coastguard Worker const char *endp; /* end of string -- virtual NUL here */ 78*9880d681SAndroid Build Coastguard Worker const char *coldp; /* can be no match starting before here */ 79*9880d681SAndroid Build Coastguard Worker const char **lastpos; /* [nplus+1] */ 80*9880d681SAndroid Build Coastguard Worker STATEVARS; 81*9880d681SAndroid Build Coastguard Worker states st; /* current states */ 82*9880d681SAndroid Build Coastguard Worker states fresh; /* states for a fresh start */ 83*9880d681SAndroid Build Coastguard Worker states tmp; /* temporary */ 84*9880d681SAndroid Build Coastguard Worker states empty; /* empty set of states */ 85*9880d681SAndroid Build Coastguard Worker}; 86*9880d681SAndroid Build Coastguard Worker 87*9880d681SAndroid Build Coastguard Workerstatic int matcher(struct re_guts *, const char *, size_t, 88*9880d681SAndroid Build Coastguard Worker llvm_regmatch_t[], int); 89*9880d681SAndroid Build Coastguard Workerstatic const char *dissect(struct match *, const char *, const char *, sopno, 90*9880d681SAndroid Build Coastguard Worker sopno); 91*9880d681SAndroid Build Coastguard Workerstatic const char *backref(struct match *, const char *, const char *, sopno, 92*9880d681SAndroid Build Coastguard Worker sopno, sopno, int); 93*9880d681SAndroid Build Coastguard Workerstatic const char *fast(struct match *, const char *, const char *, sopno, sopno); 94*9880d681SAndroid Build Coastguard Workerstatic const char *slow(struct match *, const char *, const char *, sopno, sopno); 95*9880d681SAndroid Build Coastguard Workerstatic states step(struct re_guts *, sopno, sopno, states, int, states); 96*9880d681SAndroid Build Coastguard Worker#define MAX_RECURSION 100 97*9880d681SAndroid Build Coastguard Worker#define BOL (OUT+1) 98*9880d681SAndroid Build Coastguard Worker#define EOL (BOL+1) 99*9880d681SAndroid Build Coastguard Worker#define BOLEOL (BOL+2) 100*9880d681SAndroid Build Coastguard Worker#define NOTHING (BOL+3) 101*9880d681SAndroid Build Coastguard Worker#define BOW (BOL+4) 102*9880d681SAndroid Build Coastguard Worker#define EOW (BOL+5) 103*9880d681SAndroid Build Coastguard Worker#define CODEMAX (BOL+5) /* highest code used */ 104*9880d681SAndroid Build Coastguard Worker#define NONCHAR(c) ((c) > CHAR_MAX) 105*9880d681SAndroid Build Coastguard Worker#define NNONCHAR (CODEMAX-CHAR_MAX) 106*9880d681SAndroid Build Coastguard Worker#ifdef REDEBUG 107*9880d681SAndroid Build Coastguard Workerstatic void print(struct match *, char *, states, int, FILE *); 108*9880d681SAndroid Build Coastguard Worker#endif 109*9880d681SAndroid Build Coastguard Worker#ifdef REDEBUG 110*9880d681SAndroid Build Coastguard Workerstatic void at(struct match *, char *, char *, char *, sopno, sopno); 111*9880d681SAndroid Build Coastguard Worker#endif 112*9880d681SAndroid Build Coastguard Worker#ifdef REDEBUG 113*9880d681SAndroid Build Coastguard Workerstatic char *pchar(int); 114*9880d681SAndroid Build Coastguard Worker#endif 115*9880d681SAndroid Build Coastguard Worker 116*9880d681SAndroid Build Coastguard Worker#ifdef REDEBUG 117*9880d681SAndroid Build Coastguard Worker#define SP(t, s, c) print(m, t, s, c, stdout) 118*9880d681SAndroid Build Coastguard Worker#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2) 119*9880d681SAndroid Build Coastguard Worker#define NOTE(str) { if (m->eflags®_TRACE) (void)printf("=%s\n", (str)); } 120*9880d681SAndroid Build Coastguard Workerstatic int nope = 0; 121*9880d681SAndroid Build Coastguard Worker#else 122*9880d681SAndroid Build Coastguard Worker#define SP(t, s, c) /* nothing */ 123*9880d681SAndroid Build Coastguard Worker#define AT(t, p1, p2, s1, s2) /* nothing */ 124*9880d681SAndroid Build Coastguard Worker#define NOTE(s) /* nothing */ 125*9880d681SAndroid Build Coastguard Worker#endif 126*9880d681SAndroid Build Coastguard Worker 127*9880d681SAndroid Build Coastguard Worker/* 128*9880d681SAndroid Build Coastguard Worker - matcher - the actual matching engine 129*9880d681SAndroid Build Coastguard Worker */ 130*9880d681SAndroid Build Coastguard Workerstatic int /* 0 success, REG_NOMATCH failure */ 131*9880d681SAndroid Build Coastguard Workermatcher(struct re_guts *g, const char *string, size_t nmatch, 132*9880d681SAndroid Build Coastguard Worker llvm_regmatch_t pmatch[], 133*9880d681SAndroid Build Coastguard Worker int eflags) 134*9880d681SAndroid Build Coastguard Worker{ 135*9880d681SAndroid Build Coastguard Worker const char *endp; 136*9880d681SAndroid Build Coastguard Worker size_t i; 137*9880d681SAndroid Build Coastguard Worker struct match mv; 138*9880d681SAndroid Build Coastguard Worker struct match *m = &mv; 139*9880d681SAndroid Build Coastguard Worker const char *dp; 140*9880d681SAndroid Build Coastguard Worker const sopno gf = g->firststate+1; /* +1 for OEND */ 141*9880d681SAndroid Build Coastguard Worker const sopno gl = g->laststate; 142*9880d681SAndroid Build Coastguard Worker const char *start; 143*9880d681SAndroid Build Coastguard Worker const char *stop; 144*9880d681SAndroid Build Coastguard Worker 145*9880d681SAndroid Build Coastguard Worker /* simplify the situation where possible */ 146*9880d681SAndroid Build Coastguard Worker if (g->cflags®_NOSUB) 147*9880d681SAndroid Build Coastguard Worker nmatch = 0; 148*9880d681SAndroid Build Coastguard Worker if (eflags®_STARTEND) { 149*9880d681SAndroid Build Coastguard Worker start = string + pmatch[0].rm_so; 150*9880d681SAndroid Build Coastguard Worker stop = string + pmatch[0].rm_eo; 151*9880d681SAndroid Build Coastguard Worker } else { 152*9880d681SAndroid Build Coastguard Worker start = string; 153*9880d681SAndroid Build Coastguard Worker stop = start + strlen(start); 154*9880d681SAndroid Build Coastguard Worker } 155*9880d681SAndroid Build Coastguard Worker if (stop < start) 156*9880d681SAndroid Build Coastguard Worker return(REG_INVARG); 157*9880d681SAndroid Build Coastguard Worker 158*9880d681SAndroid Build Coastguard Worker /* prescreening; this does wonders for this rather slow code */ 159*9880d681SAndroid Build Coastguard Worker if (g->must != NULL) { 160*9880d681SAndroid Build Coastguard Worker for (dp = start; dp < stop; dp++) 161*9880d681SAndroid Build Coastguard Worker if (*dp == g->must[0] && stop - dp >= g->mlen && 162*9880d681SAndroid Build Coastguard Worker memcmp(dp, g->must, (size_t)g->mlen) == 0) 163*9880d681SAndroid Build Coastguard Worker break; 164*9880d681SAndroid Build Coastguard Worker if (dp == stop) /* we didn't find g->must */ 165*9880d681SAndroid Build Coastguard Worker return(REG_NOMATCH); 166*9880d681SAndroid Build Coastguard Worker } 167*9880d681SAndroid Build Coastguard Worker 168*9880d681SAndroid Build Coastguard Worker /* match struct setup */ 169*9880d681SAndroid Build Coastguard Worker m->g = g; 170*9880d681SAndroid Build Coastguard Worker m->eflags = eflags; 171*9880d681SAndroid Build Coastguard Worker m->pmatch = NULL; 172*9880d681SAndroid Build Coastguard Worker m->lastpos = NULL; 173*9880d681SAndroid Build Coastguard Worker m->offp = string; 174*9880d681SAndroid Build Coastguard Worker m->beginp = start; 175*9880d681SAndroid Build Coastguard Worker m->endp = stop; 176*9880d681SAndroid Build Coastguard Worker STATESETUP(m, 4); 177*9880d681SAndroid Build Coastguard Worker SETUP(m->st); 178*9880d681SAndroid Build Coastguard Worker SETUP(m->fresh); 179*9880d681SAndroid Build Coastguard Worker SETUP(m->tmp); 180*9880d681SAndroid Build Coastguard Worker SETUP(m->empty); 181*9880d681SAndroid Build Coastguard Worker CLEAR(m->empty); 182*9880d681SAndroid Build Coastguard Worker 183*9880d681SAndroid Build Coastguard Worker /* this loop does only one repetition except for backrefs */ 184*9880d681SAndroid Build Coastguard Worker for (;;) { 185*9880d681SAndroid Build Coastguard Worker endp = fast(m, start, stop, gf, gl); 186*9880d681SAndroid Build Coastguard Worker if (endp == NULL) { /* a miss */ 187*9880d681SAndroid Build Coastguard Worker free(m->pmatch); 188*9880d681SAndroid Build Coastguard Worker free((void*)m->lastpos); 189*9880d681SAndroid Build Coastguard Worker STATETEARDOWN(m); 190*9880d681SAndroid Build Coastguard Worker return(REG_NOMATCH); 191*9880d681SAndroid Build Coastguard Worker } 192*9880d681SAndroid Build Coastguard Worker if (nmatch == 0 && !g->backrefs) 193*9880d681SAndroid Build Coastguard Worker break; /* no further info needed */ 194*9880d681SAndroid Build Coastguard Worker 195*9880d681SAndroid Build Coastguard Worker /* where? */ 196*9880d681SAndroid Build Coastguard Worker assert(m->coldp != NULL); 197*9880d681SAndroid Build Coastguard Worker for (;;) { 198*9880d681SAndroid Build Coastguard Worker NOTE("finding start"); 199*9880d681SAndroid Build Coastguard Worker endp = slow(m, m->coldp, stop, gf, gl); 200*9880d681SAndroid Build Coastguard Worker if (endp != NULL) 201*9880d681SAndroid Build Coastguard Worker break; 202*9880d681SAndroid Build Coastguard Worker assert(m->coldp < m->endp); 203*9880d681SAndroid Build Coastguard Worker m->coldp++; 204*9880d681SAndroid Build Coastguard Worker } 205*9880d681SAndroid Build Coastguard Worker if (nmatch == 1 && !g->backrefs) 206*9880d681SAndroid Build Coastguard Worker break; /* no further info needed */ 207*9880d681SAndroid Build Coastguard Worker 208*9880d681SAndroid Build Coastguard Worker /* oh my, they want the subexpressions... */ 209*9880d681SAndroid Build Coastguard Worker if (m->pmatch == NULL) 210*9880d681SAndroid Build Coastguard Worker m->pmatch = (llvm_regmatch_t *)malloc((m->g->nsub + 1) * 211*9880d681SAndroid Build Coastguard Worker sizeof(llvm_regmatch_t)); 212*9880d681SAndroid Build Coastguard Worker if (m->pmatch == NULL) { 213*9880d681SAndroid Build Coastguard Worker STATETEARDOWN(m); 214*9880d681SAndroid Build Coastguard Worker return(REG_ESPACE); 215*9880d681SAndroid Build Coastguard Worker } 216*9880d681SAndroid Build Coastguard Worker for (i = 1; i <= m->g->nsub; i++) 217*9880d681SAndroid Build Coastguard Worker m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1; 218*9880d681SAndroid Build Coastguard Worker if (!g->backrefs && !(m->eflags®_BACKR)) { 219*9880d681SAndroid Build Coastguard Worker NOTE("dissecting"); 220*9880d681SAndroid Build Coastguard Worker dp = dissect(m, m->coldp, endp, gf, gl); 221*9880d681SAndroid Build Coastguard Worker } else { 222*9880d681SAndroid Build Coastguard Worker if (g->nplus > 0 && m->lastpos == NULL) 223*9880d681SAndroid Build Coastguard Worker m->lastpos = (const char **)malloc((g->nplus+1) * 224*9880d681SAndroid Build Coastguard Worker sizeof(char *)); 225*9880d681SAndroid Build Coastguard Worker if (g->nplus > 0 && m->lastpos == NULL) { 226*9880d681SAndroid Build Coastguard Worker free(m->pmatch); 227*9880d681SAndroid Build Coastguard Worker STATETEARDOWN(m); 228*9880d681SAndroid Build Coastguard Worker return(REG_ESPACE); 229*9880d681SAndroid Build Coastguard Worker } 230*9880d681SAndroid Build Coastguard Worker NOTE("backref dissect"); 231*9880d681SAndroid Build Coastguard Worker dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0); 232*9880d681SAndroid Build Coastguard Worker } 233*9880d681SAndroid Build Coastguard Worker if (dp != NULL) 234*9880d681SAndroid Build Coastguard Worker break; 235*9880d681SAndroid Build Coastguard Worker 236*9880d681SAndroid Build Coastguard Worker /* uh-oh... we couldn't find a subexpression-level match */ 237*9880d681SAndroid Build Coastguard Worker assert(g->backrefs); /* must be back references doing it */ 238*9880d681SAndroid Build Coastguard Worker assert(g->nplus == 0 || m->lastpos != NULL); 239*9880d681SAndroid Build Coastguard Worker for (;;) { 240*9880d681SAndroid Build Coastguard Worker if (dp != NULL || endp <= m->coldp) 241*9880d681SAndroid Build Coastguard Worker break; /* defeat */ 242*9880d681SAndroid Build Coastguard Worker NOTE("backoff"); 243*9880d681SAndroid Build Coastguard Worker endp = slow(m, m->coldp, endp-1, gf, gl); 244*9880d681SAndroid Build Coastguard Worker if (endp == NULL) 245*9880d681SAndroid Build Coastguard Worker break; /* defeat */ 246*9880d681SAndroid Build Coastguard Worker /* try it on a shorter possibility */ 247*9880d681SAndroid Build Coastguard Worker#ifndef NDEBUG 248*9880d681SAndroid Build Coastguard Worker for (i = 1; i <= m->g->nsub; i++) { 249*9880d681SAndroid Build Coastguard Worker assert(m->pmatch[i].rm_so == -1); 250*9880d681SAndroid Build Coastguard Worker assert(m->pmatch[i].rm_eo == -1); 251*9880d681SAndroid Build Coastguard Worker } 252*9880d681SAndroid Build Coastguard Worker#endif 253*9880d681SAndroid Build Coastguard Worker NOTE("backoff dissect"); 254*9880d681SAndroid Build Coastguard Worker dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0); 255*9880d681SAndroid Build Coastguard Worker } 256*9880d681SAndroid Build Coastguard Worker assert(dp == NULL || dp == endp); 257*9880d681SAndroid Build Coastguard Worker if (dp != NULL) /* found a shorter one */ 258*9880d681SAndroid Build Coastguard Worker break; 259*9880d681SAndroid Build Coastguard Worker 260*9880d681SAndroid Build Coastguard Worker /* despite initial appearances, there is no match here */ 261*9880d681SAndroid Build Coastguard Worker NOTE("false alarm"); 262*9880d681SAndroid Build Coastguard Worker if (m->coldp == stop) 263*9880d681SAndroid Build Coastguard Worker break; 264*9880d681SAndroid Build Coastguard Worker start = m->coldp + 1; /* recycle starting later */ 265*9880d681SAndroid Build Coastguard Worker } 266*9880d681SAndroid Build Coastguard Worker 267*9880d681SAndroid Build Coastguard Worker /* fill in the details if requested */ 268*9880d681SAndroid Build Coastguard Worker if (nmatch > 0) { 269*9880d681SAndroid Build Coastguard Worker pmatch[0].rm_so = m->coldp - m->offp; 270*9880d681SAndroid Build Coastguard Worker pmatch[0].rm_eo = endp - m->offp; 271*9880d681SAndroid Build Coastguard Worker } 272*9880d681SAndroid Build Coastguard Worker if (nmatch > 1) { 273*9880d681SAndroid Build Coastguard Worker assert(m->pmatch != NULL); 274*9880d681SAndroid Build Coastguard Worker for (i = 1; i < nmatch; i++) 275*9880d681SAndroid Build Coastguard Worker if (i <= m->g->nsub) 276*9880d681SAndroid Build Coastguard Worker pmatch[i] = m->pmatch[i]; 277*9880d681SAndroid Build Coastguard Worker else { 278*9880d681SAndroid Build Coastguard Worker pmatch[i].rm_so = -1; 279*9880d681SAndroid Build Coastguard Worker pmatch[i].rm_eo = -1; 280*9880d681SAndroid Build Coastguard Worker } 281*9880d681SAndroid Build Coastguard Worker } 282*9880d681SAndroid Build Coastguard Worker 283*9880d681SAndroid Build Coastguard Worker if (m->pmatch != NULL) 284*9880d681SAndroid Build Coastguard Worker free((char *)m->pmatch); 285*9880d681SAndroid Build Coastguard Worker if (m->lastpos != NULL) 286*9880d681SAndroid Build Coastguard Worker free((char *)m->lastpos); 287*9880d681SAndroid Build Coastguard Worker STATETEARDOWN(m); 288*9880d681SAndroid Build Coastguard Worker return(0); 289*9880d681SAndroid Build Coastguard Worker} 290*9880d681SAndroid Build Coastguard Worker 291*9880d681SAndroid Build Coastguard Worker/* 292*9880d681SAndroid Build Coastguard Worker - dissect - figure out what matched what, no back references 293*9880d681SAndroid Build Coastguard Worker */ 294*9880d681SAndroid Build Coastguard Workerstatic const char * /* == stop (success) always */ 295*9880d681SAndroid Build Coastguard Workerdissect(struct match *m, const char *start, const char *stop, sopno startst, 296*9880d681SAndroid Build Coastguard Worker sopno stopst) 297*9880d681SAndroid Build Coastguard Worker{ 298*9880d681SAndroid Build Coastguard Worker int i; 299*9880d681SAndroid Build Coastguard Worker sopno ss; /* start sop of current subRE */ 300*9880d681SAndroid Build Coastguard Worker sopno es; /* end sop of current subRE */ 301*9880d681SAndroid Build Coastguard Worker const char *sp; /* start of string matched by it */ 302*9880d681SAndroid Build Coastguard Worker const char *stp; /* string matched by it cannot pass here */ 303*9880d681SAndroid Build Coastguard Worker const char *rest; /* start of rest of string */ 304*9880d681SAndroid Build Coastguard Worker const char *tail; /* string unmatched by rest of RE */ 305*9880d681SAndroid Build Coastguard Worker sopno ssub; /* start sop of subsubRE */ 306*9880d681SAndroid Build Coastguard Worker sopno esub; /* end sop of subsubRE */ 307*9880d681SAndroid Build Coastguard Worker const char *ssp; /* start of string matched by subsubRE */ 308*9880d681SAndroid Build Coastguard Worker const char *sep; /* end of string matched by subsubRE */ 309*9880d681SAndroid Build Coastguard Worker const char *oldssp; /* previous ssp */ 310*9880d681SAndroid Build Coastguard Worker 311*9880d681SAndroid Build Coastguard Worker AT("diss", start, stop, startst, stopst); 312*9880d681SAndroid Build Coastguard Worker sp = start; 313*9880d681SAndroid Build Coastguard Worker for (ss = startst; ss < stopst; ss = es) { 314*9880d681SAndroid Build Coastguard Worker /* identify end of subRE */ 315*9880d681SAndroid Build Coastguard Worker es = ss; 316*9880d681SAndroid Build Coastguard Worker switch (OP(m->g->strip[es])) { 317*9880d681SAndroid Build Coastguard Worker case OPLUS_: 318*9880d681SAndroid Build Coastguard Worker case OQUEST_: 319*9880d681SAndroid Build Coastguard Worker es += OPND(m->g->strip[es]); 320*9880d681SAndroid Build Coastguard Worker break; 321*9880d681SAndroid Build Coastguard Worker case OCH_: 322*9880d681SAndroid Build Coastguard Worker while (OP(m->g->strip[es]) != O_CH) 323*9880d681SAndroid Build Coastguard Worker es += OPND(m->g->strip[es]); 324*9880d681SAndroid Build Coastguard Worker break; 325*9880d681SAndroid Build Coastguard Worker } 326*9880d681SAndroid Build Coastguard Worker es++; 327*9880d681SAndroid Build Coastguard Worker 328*9880d681SAndroid Build Coastguard Worker /* figure out what it matched */ 329*9880d681SAndroid Build Coastguard Worker switch (OP(m->g->strip[ss])) { 330*9880d681SAndroid Build Coastguard Worker case OEND: 331*9880d681SAndroid Build Coastguard Worker assert(nope); 332*9880d681SAndroid Build Coastguard Worker break; 333*9880d681SAndroid Build Coastguard Worker case OCHAR: 334*9880d681SAndroid Build Coastguard Worker sp++; 335*9880d681SAndroid Build Coastguard Worker break; 336*9880d681SAndroid Build Coastguard Worker case OBOL: 337*9880d681SAndroid Build Coastguard Worker case OEOL: 338*9880d681SAndroid Build Coastguard Worker case OBOW: 339*9880d681SAndroid Build Coastguard Worker case OEOW: 340*9880d681SAndroid Build Coastguard Worker break; 341*9880d681SAndroid Build Coastguard Worker case OANY: 342*9880d681SAndroid Build Coastguard Worker case OANYOF: 343*9880d681SAndroid Build Coastguard Worker sp++; 344*9880d681SAndroid Build Coastguard Worker break; 345*9880d681SAndroid Build Coastguard Worker case OBACK_: 346*9880d681SAndroid Build Coastguard Worker case O_BACK: 347*9880d681SAndroid Build Coastguard Worker assert(nope); 348*9880d681SAndroid Build Coastguard Worker break; 349*9880d681SAndroid Build Coastguard Worker /* cases where length of match is hard to find */ 350*9880d681SAndroid Build Coastguard Worker case OQUEST_: 351*9880d681SAndroid Build Coastguard Worker stp = stop; 352*9880d681SAndroid Build Coastguard Worker for (;;) { 353*9880d681SAndroid Build Coastguard Worker /* how long could this one be? */ 354*9880d681SAndroid Build Coastguard Worker rest = slow(m, sp, stp, ss, es); 355*9880d681SAndroid Build Coastguard Worker assert(rest != NULL); /* it did match */ 356*9880d681SAndroid Build Coastguard Worker /* could the rest match the rest? */ 357*9880d681SAndroid Build Coastguard Worker tail = slow(m, rest, stop, es, stopst); 358*9880d681SAndroid Build Coastguard Worker if (tail == stop) 359*9880d681SAndroid Build Coastguard Worker break; /* yes! */ 360*9880d681SAndroid Build Coastguard Worker /* no -- try a shorter match for this one */ 361*9880d681SAndroid Build Coastguard Worker stp = rest - 1; 362*9880d681SAndroid Build Coastguard Worker assert(stp >= sp); /* it did work */ 363*9880d681SAndroid Build Coastguard Worker } 364*9880d681SAndroid Build Coastguard Worker ssub = ss + 1; 365*9880d681SAndroid Build Coastguard Worker esub = es - 1; 366*9880d681SAndroid Build Coastguard Worker /* did innards match? */ 367*9880d681SAndroid Build Coastguard Worker if (slow(m, sp, rest, ssub, esub) != NULL) { 368*9880d681SAndroid Build Coastguard Worker const char *dp = dissect(m, sp, rest, ssub, esub); 369*9880d681SAndroid Build Coastguard Worker (void)dp; /* avoid warning if assertions off */ 370*9880d681SAndroid Build Coastguard Worker assert(dp == rest); 371*9880d681SAndroid Build Coastguard Worker } else /* no */ 372*9880d681SAndroid Build Coastguard Worker assert(sp == rest); 373*9880d681SAndroid Build Coastguard Worker sp = rest; 374*9880d681SAndroid Build Coastguard Worker break; 375*9880d681SAndroid Build Coastguard Worker case OPLUS_: 376*9880d681SAndroid Build Coastguard Worker stp = stop; 377*9880d681SAndroid Build Coastguard Worker for (;;) { 378*9880d681SAndroid Build Coastguard Worker /* how long could this one be? */ 379*9880d681SAndroid Build Coastguard Worker rest = slow(m, sp, stp, ss, es); 380*9880d681SAndroid Build Coastguard Worker assert(rest != NULL); /* it did match */ 381*9880d681SAndroid Build Coastguard Worker /* could the rest match the rest? */ 382*9880d681SAndroid Build Coastguard Worker tail = slow(m, rest, stop, es, stopst); 383*9880d681SAndroid Build Coastguard Worker if (tail == stop) 384*9880d681SAndroid Build Coastguard Worker break; /* yes! */ 385*9880d681SAndroid Build Coastguard Worker /* no -- try a shorter match for this one */ 386*9880d681SAndroid Build Coastguard Worker stp = rest - 1; 387*9880d681SAndroid Build Coastguard Worker assert(stp >= sp); /* it did work */ 388*9880d681SAndroid Build Coastguard Worker } 389*9880d681SAndroid Build Coastguard Worker ssub = ss + 1; 390*9880d681SAndroid Build Coastguard Worker esub = es - 1; 391*9880d681SAndroid Build Coastguard Worker ssp = sp; 392*9880d681SAndroid Build Coastguard Worker oldssp = ssp; 393*9880d681SAndroid Build Coastguard Worker for (;;) { /* find last match of innards */ 394*9880d681SAndroid Build Coastguard Worker sep = slow(m, ssp, rest, ssub, esub); 395*9880d681SAndroid Build Coastguard Worker if (sep == NULL || sep == ssp) 396*9880d681SAndroid Build Coastguard Worker break; /* failed or matched null */ 397*9880d681SAndroid Build Coastguard Worker oldssp = ssp; /* on to next try */ 398*9880d681SAndroid Build Coastguard Worker ssp = sep; 399*9880d681SAndroid Build Coastguard Worker } 400*9880d681SAndroid Build Coastguard Worker if (sep == NULL) { 401*9880d681SAndroid Build Coastguard Worker /* last successful match */ 402*9880d681SAndroid Build Coastguard Worker sep = ssp; 403*9880d681SAndroid Build Coastguard Worker ssp = oldssp; 404*9880d681SAndroid Build Coastguard Worker } 405*9880d681SAndroid Build Coastguard Worker assert(sep == rest); /* must exhaust substring */ 406*9880d681SAndroid Build Coastguard Worker assert(slow(m, ssp, sep, ssub, esub) == rest); 407*9880d681SAndroid Build Coastguard Worker { 408*9880d681SAndroid Build Coastguard Worker const char *dp = dissect(m, ssp, sep, ssub, esub); 409*9880d681SAndroid Build Coastguard Worker (void)dp; /* avoid warning if assertions off */ 410*9880d681SAndroid Build Coastguard Worker assert(dp == sep); 411*9880d681SAndroid Build Coastguard Worker } 412*9880d681SAndroid Build Coastguard Worker sp = rest; 413*9880d681SAndroid Build Coastguard Worker break; 414*9880d681SAndroid Build Coastguard Worker case OCH_: 415*9880d681SAndroid Build Coastguard Worker stp = stop; 416*9880d681SAndroid Build Coastguard Worker for (;;) { 417*9880d681SAndroid Build Coastguard Worker /* how long could this one be? */ 418*9880d681SAndroid Build Coastguard Worker rest = slow(m, sp, stp, ss, es); 419*9880d681SAndroid Build Coastguard Worker assert(rest != NULL); /* it did match */ 420*9880d681SAndroid Build Coastguard Worker /* could the rest match the rest? */ 421*9880d681SAndroid Build Coastguard Worker tail = slow(m, rest, stop, es, stopst); 422*9880d681SAndroid Build Coastguard Worker if (tail == stop) 423*9880d681SAndroid Build Coastguard Worker break; /* yes! */ 424*9880d681SAndroid Build Coastguard Worker /* no -- try a shorter match for this one */ 425*9880d681SAndroid Build Coastguard Worker stp = rest - 1; 426*9880d681SAndroid Build Coastguard Worker assert(stp >= sp); /* it did work */ 427*9880d681SAndroid Build Coastguard Worker } 428*9880d681SAndroid Build Coastguard Worker ssub = ss + 1; 429*9880d681SAndroid Build Coastguard Worker esub = ss + OPND(m->g->strip[ss]) - 1; 430*9880d681SAndroid Build Coastguard Worker assert(OP(m->g->strip[esub]) == OOR1); 431*9880d681SAndroid Build Coastguard Worker for (;;) { /* find first matching branch */ 432*9880d681SAndroid Build Coastguard Worker if (slow(m, sp, rest, ssub, esub) == rest) 433*9880d681SAndroid Build Coastguard Worker break; /* it matched all of it */ 434*9880d681SAndroid Build Coastguard Worker /* that one missed, try next one */ 435*9880d681SAndroid Build Coastguard Worker assert(OP(m->g->strip[esub]) == OOR1); 436*9880d681SAndroid Build Coastguard Worker esub++; 437*9880d681SAndroid Build Coastguard Worker assert(OP(m->g->strip[esub]) == OOR2); 438*9880d681SAndroid Build Coastguard Worker ssub = esub + 1; 439*9880d681SAndroid Build Coastguard Worker esub += OPND(m->g->strip[esub]); 440*9880d681SAndroid Build Coastguard Worker if (OP(m->g->strip[esub]) == OOR2) 441*9880d681SAndroid Build Coastguard Worker esub--; 442*9880d681SAndroid Build Coastguard Worker else 443*9880d681SAndroid Build Coastguard Worker assert(OP(m->g->strip[esub]) == O_CH); 444*9880d681SAndroid Build Coastguard Worker } 445*9880d681SAndroid Build Coastguard Worker { 446*9880d681SAndroid Build Coastguard Worker const char *dp = dissect(m, sp, rest, ssub, esub); 447*9880d681SAndroid Build Coastguard Worker (void)dp; /* avoid warning if assertions off */ 448*9880d681SAndroid Build Coastguard Worker assert(dp == rest); 449*9880d681SAndroid Build Coastguard Worker } 450*9880d681SAndroid Build Coastguard Worker sp = rest; 451*9880d681SAndroid Build Coastguard Worker break; 452*9880d681SAndroid Build Coastguard Worker case O_PLUS: 453*9880d681SAndroid Build Coastguard Worker case O_QUEST: 454*9880d681SAndroid Build Coastguard Worker case OOR1: 455*9880d681SAndroid Build Coastguard Worker case OOR2: 456*9880d681SAndroid Build Coastguard Worker case O_CH: 457*9880d681SAndroid Build Coastguard Worker assert(nope); 458*9880d681SAndroid Build Coastguard Worker break; 459*9880d681SAndroid Build Coastguard Worker case OLPAREN: 460*9880d681SAndroid Build Coastguard Worker i = OPND(m->g->strip[ss]); 461*9880d681SAndroid Build Coastguard Worker assert(0 < i && i <= m->g->nsub); 462*9880d681SAndroid Build Coastguard Worker m->pmatch[i].rm_so = sp - m->offp; 463*9880d681SAndroid Build Coastguard Worker break; 464*9880d681SAndroid Build Coastguard Worker case ORPAREN: 465*9880d681SAndroid Build Coastguard Worker i = OPND(m->g->strip[ss]); 466*9880d681SAndroid Build Coastguard Worker assert(0 < i && i <= m->g->nsub); 467*9880d681SAndroid Build Coastguard Worker m->pmatch[i].rm_eo = sp - m->offp; 468*9880d681SAndroid Build Coastguard Worker break; 469*9880d681SAndroid Build Coastguard Worker default: /* uh oh */ 470*9880d681SAndroid Build Coastguard Worker assert(nope); 471*9880d681SAndroid Build Coastguard Worker break; 472*9880d681SAndroid Build Coastguard Worker } 473*9880d681SAndroid Build Coastguard Worker } 474*9880d681SAndroid Build Coastguard Worker 475*9880d681SAndroid Build Coastguard Worker assert(sp == stop); 476*9880d681SAndroid Build Coastguard Worker return(sp); 477*9880d681SAndroid Build Coastguard Worker} 478*9880d681SAndroid Build Coastguard Worker 479*9880d681SAndroid Build Coastguard Worker/* 480*9880d681SAndroid Build Coastguard Worker - backref - figure out what matched what, figuring in back references 481*9880d681SAndroid Build Coastguard Worker */ 482*9880d681SAndroid Build Coastguard Workerstatic const char * /* == stop (success) or NULL (failure) */ 483*9880d681SAndroid Build Coastguard Workerbackref(struct match *m, const char *start, const char *stop, sopno startst, 484*9880d681SAndroid Build Coastguard Worker sopno stopst, sopno lev, int rec) /* PLUS nesting level */ 485*9880d681SAndroid Build Coastguard Worker{ 486*9880d681SAndroid Build Coastguard Worker int i; 487*9880d681SAndroid Build Coastguard Worker sopno ss; /* start sop of current subRE */ 488*9880d681SAndroid Build Coastguard Worker const char *sp; /* start of string matched by it */ 489*9880d681SAndroid Build Coastguard Worker sopno ssub; /* start sop of subsubRE */ 490*9880d681SAndroid Build Coastguard Worker sopno esub; /* end sop of subsubRE */ 491*9880d681SAndroid Build Coastguard Worker const char *ssp; /* start of string matched by subsubRE */ 492*9880d681SAndroid Build Coastguard Worker const char *dp; 493*9880d681SAndroid Build Coastguard Worker size_t len; 494*9880d681SAndroid Build Coastguard Worker int hard; 495*9880d681SAndroid Build Coastguard Worker sop s; 496*9880d681SAndroid Build Coastguard Worker llvm_regoff_t offsave; 497*9880d681SAndroid Build Coastguard Worker cset *cs; 498*9880d681SAndroid Build Coastguard Worker 499*9880d681SAndroid Build Coastguard Worker AT("back", start, stop, startst, stopst); 500*9880d681SAndroid Build Coastguard Worker sp = start; 501*9880d681SAndroid Build Coastguard Worker 502*9880d681SAndroid Build Coastguard Worker /* get as far as we can with easy stuff */ 503*9880d681SAndroid Build Coastguard Worker hard = 0; 504*9880d681SAndroid Build Coastguard Worker for (ss = startst; !hard && ss < stopst; ss++) 505*9880d681SAndroid Build Coastguard Worker switch (OP(s = m->g->strip[ss])) { 506*9880d681SAndroid Build Coastguard Worker case OCHAR: 507*9880d681SAndroid Build Coastguard Worker if (sp == stop || *sp++ != (char)OPND(s)) 508*9880d681SAndroid Build Coastguard Worker return(NULL); 509*9880d681SAndroid Build Coastguard Worker break; 510*9880d681SAndroid Build Coastguard Worker case OANY: 511*9880d681SAndroid Build Coastguard Worker if (sp == stop) 512*9880d681SAndroid Build Coastguard Worker return(NULL); 513*9880d681SAndroid Build Coastguard Worker sp++; 514*9880d681SAndroid Build Coastguard Worker break; 515*9880d681SAndroid Build Coastguard Worker case OANYOF: 516*9880d681SAndroid Build Coastguard Worker cs = &m->g->sets[OPND(s)]; 517*9880d681SAndroid Build Coastguard Worker if (sp == stop || !CHIN(cs, *sp++)) 518*9880d681SAndroid Build Coastguard Worker return(NULL); 519*9880d681SAndroid Build Coastguard Worker break; 520*9880d681SAndroid Build Coastguard Worker case OBOL: 521*9880d681SAndroid Build Coastguard Worker if ( (sp == m->beginp && !(m->eflags®_NOTBOL)) || 522*9880d681SAndroid Build Coastguard Worker (sp < m->endp && *(sp-1) == '\n' && 523*9880d681SAndroid Build Coastguard Worker (m->g->cflags®_NEWLINE)) ) 524*9880d681SAndroid Build Coastguard Worker { /* yes */ } 525*9880d681SAndroid Build Coastguard Worker else 526*9880d681SAndroid Build Coastguard Worker return(NULL); 527*9880d681SAndroid Build Coastguard Worker break; 528*9880d681SAndroid Build Coastguard Worker case OEOL: 529*9880d681SAndroid Build Coastguard Worker if ( (sp == m->endp && !(m->eflags®_NOTEOL)) || 530*9880d681SAndroid Build Coastguard Worker (sp < m->endp && *sp == '\n' && 531*9880d681SAndroid Build Coastguard Worker (m->g->cflags®_NEWLINE)) ) 532*9880d681SAndroid Build Coastguard Worker { /* yes */ } 533*9880d681SAndroid Build Coastguard Worker else 534*9880d681SAndroid Build Coastguard Worker return(NULL); 535*9880d681SAndroid Build Coastguard Worker break; 536*9880d681SAndroid Build Coastguard Worker case OBOW: 537*9880d681SAndroid Build Coastguard Worker if (( (sp == m->beginp && !(m->eflags®_NOTBOL)) || 538*9880d681SAndroid Build Coastguard Worker (sp < m->endp && *(sp-1) == '\n' && 539*9880d681SAndroid Build Coastguard Worker (m->g->cflags®_NEWLINE)) || 540*9880d681SAndroid Build Coastguard Worker (sp > m->beginp && 541*9880d681SAndroid Build Coastguard Worker !ISWORD(*(sp-1))) ) && 542*9880d681SAndroid Build Coastguard Worker (sp < m->endp && ISWORD(*sp)) ) 543*9880d681SAndroid Build Coastguard Worker { /* yes */ } 544*9880d681SAndroid Build Coastguard Worker else 545*9880d681SAndroid Build Coastguard Worker return(NULL); 546*9880d681SAndroid Build Coastguard Worker break; 547*9880d681SAndroid Build Coastguard Worker case OEOW: 548*9880d681SAndroid Build Coastguard Worker if (( (sp == m->endp && !(m->eflags®_NOTEOL)) || 549*9880d681SAndroid Build Coastguard Worker (sp < m->endp && *sp == '\n' && 550*9880d681SAndroid Build Coastguard Worker (m->g->cflags®_NEWLINE)) || 551*9880d681SAndroid Build Coastguard Worker (sp < m->endp && !ISWORD(*sp)) ) && 552*9880d681SAndroid Build Coastguard Worker (sp > m->beginp && ISWORD(*(sp-1))) ) 553*9880d681SAndroid Build Coastguard Worker { /* yes */ } 554*9880d681SAndroid Build Coastguard Worker else 555*9880d681SAndroid Build Coastguard Worker return(NULL); 556*9880d681SAndroid Build Coastguard Worker break; 557*9880d681SAndroid Build Coastguard Worker case O_QUEST: 558*9880d681SAndroid Build Coastguard Worker break; 559*9880d681SAndroid Build Coastguard Worker case OOR1: /* matches null but needs to skip */ 560*9880d681SAndroid Build Coastguard Worker ss++; 561*9880d681SAndroid Build Coastguard Worker s = m->g->strip[ss]; 562*9880d681SAndroid Build Coastguard Worker do { 563*9880d681SAndroid Build Coastguard Worker assert(OP(s) == OOR2); 564*9880d681SAndroid Build Coastguard Worker ss += OPND(s); 565*9880d681SAndroid Build Coastguard Worker } while (OP(s = m->g->strip[ss]) != O_CH); 566*9880d681SAndroid Build Coastguard Worker /* note that the ss++ gets us past the O_CH */ 567*9880d681SAndroid Build Coastguard Worker break; 568*9880d681SAndroid Build Coastguard Worker default: /* have to make a choice */ 569*9880d681SAndroid Build Coastguard Worker hard = 1; 570*9880d681SAndroid Build Coastguard Worker break; 571*9880d681SAndroid Build Coastguard Worker } 572*9880d681SAndroid Build Coastguard Worker if (!hard) { /* that was it! */ 573*9880d681SAndroid Build Coastguard Worker if (sp != stop) 574*9880d681SAndroid Build Coastguard Worker return(NULL); 575*9880d681SAndroid Build Coastguard Worker return(sp); 576*9880d681SAndroid Build Coastguard Worker } 577*9880d681SAndroid Build Coastguard Worker ss--; /* adjust for the for's final increment */ 578*9880d681SAndroid Build Coastguard Worker 579*9880d681SAndroid Build Coastguard Worker /* the hard stuff */ 580*9880d681SAndroid Build Coastguard Worker AT("hard", sp, stop, ss, stopst); 581*9880d681SAndroid Build Coastguard Worker s = m->g->strip[ss]; 582*9880d681SAndroid Build Coastguard Worker switch (OP(s)) { 583*9880d681SAndroid Build Coastguard Worker case OBACK_: /* the vilest depths */ 584*9880d681SAndroid Build Coastguard Worker i = OPND(s); 585*9880d681SAndroid Build Coastguard Worker assert(0 < i && i <= m->g->nsub); 586*9880d681SAndroid Build Coastguard Worker if (m->pmatch[i].rm_eo == -1) 587*9880d681SAndroid Build Coastguard Worker return(NULL); 588*9880d681SAndroid Build Coastguard Worker assert(m->pmatch[i].rm_so != -1); 589*9880d681SAndroid Build Coastguard Worker len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so; 590*9880d681SAndroid Build Coastguard Worker if (len == 0 && rec++ > MAX_RECURSION) 591*9880d681SAndroid Build Coastguard Worker return(NULL); 592*9880d681SAndroid Build Coastguard Worker assert(stop - m->beginp >= len); 593*9880d681SAndroid Build Coastguard Worker if (sp > stop - len) 594*9880d681SAndroid Build Coastguard Worker return(NULL); /* not enough left to match */ 595*9880d681SAndroid Build Coastguard Worker ssp = m->offp + m->pmatch[i].rm_so; 596*9880d681SAndroid Build Coastguard Worker if (memcmp(sp, ssp, len) != 0) 597*9880d681SAndroid Build Coastguard Worker return(NULL); 598*9880d681SAndroid Build Coastguard Worker while (m->g->strip[ss] != SOP(O_BACK, i)) 599*9880d681SAndroid Build Coastguard Worker ss++; 600*9880d681SAndroid Build Coastguard Worker return(backref(m, sp+len, stop, ss+1, stopst, lev, rec)); 601*9880d681SAndroid Build Coastguard Worker break; 602*9880d681SAndroid Build Coastguard Worker case OQUEST_: /* to null or not */ 603*9880d681SAndroid Build Coastguard Worker dp = backref(m, sp, stop, ss+1, stopst, lev, rec); 604*9880d681SAndroid Build Coastguard Worker if (dp != NULL) 605*9880d681SAndroid Build Coastguard Worker return(dp); /* not */ 606*9880d681SAndroid Build Coastguard Worker return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev, rec)); 607*9880d681SAndroid Build Coastguard Worker break; 608*9880d681SAndroid Build Coastguard Worker case OPLUS_: 609*9880d681SAndroid Build Coastguard Worker assert(m->lastpos != NULL); 610*9880d681SAndroid Build Coastguard Worker assert(lev+1 <= m->g->nplus); 611*9880d681SAndroid Build Coastguard Worker m->lastpos[lev+1] = sp; 612*9880d681SAndroid Build Coastguard Worker return(backref(m, sp, stop, ss+1, stopst, lev+1, rec)); 613*9880d681SAndroid Build Coastguard Worker break; 614*9880d681SAndroid Build Coastguard Worker case O_PLUS: 615*9880d681SAndroid Build Coastguard Worker if (sp == m->lastpos[lev]) /* last pass matched null */ 616*9880d681SAndroid Build Coastguard Worker return(backref(m, sp, stop, ss+1, stopst, lev-1, rec)); 617*9880d681SAndroid Build Coastguard Worker /* try another pass */ 618*9880d681SAndroid Build Coastguard Worker m->lastpos[lev] = sp; 619*9880d681SAndroid Build Coastguard Worker dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev, rec); 620*9880d681SAndroid Build Coastguard Worker if (dp == NULL) 621*9880d681SAndroid Build Coastguard Worker return(backref(m, sp, stop, ss+1, stopst, lev-1, rec)); 622*9880d681SAndroid Build Coastguard Worker else 623*9880d681SAndroid Build Coastguard Worker return(dp); 624*9880d681SAndroid Build Coastguard Worker break; 625*9880d681SAndroid Build Coastguard Worker case OCH_: /* find the right one, if any */ 626*9880d681SAndroid Build Coastguard Worker ssub = ss + 1; 627*9880d681SAndroid Build Coastguard Worker esub = ss + OPND(s) - 1; 628*9880d681SAndroid Build Coastguard Worker assert(OP(m->g->strip[esub]) == OOR1); 629*9880d681SAndroid Build Coastguard Worker for (;;) { /* find first matching branch */ 630*9880d681SAndroid Build Coastguard Worker dp = backref(m, sp, stop, ssub, esub, lev, rec); 631*9880d681SAndroid Build Coastguard Worker if (dp != NULL) 632*9880d681SAndroid Build Coastguard Worker return(dp); 633*9880d681SAndroid Build Coastguard Worker /* that one missed, try next one */ 634*9880d681SAndroid Build Coastguard Worker if (OP(m->g->strip[esub]) == O_CH) 635*9880d681SAndroid Build Coastguard Worker return(NULL); /* there is none */ 636*9880d681SAndroid Build Coastguard Worker esub++; 637*9880d681SAndroid Build Coastguard Worker assert(OP(m->g->strip[esub]) == OOR2); 638*9880d681SAndroid Build Coastguard Worker ssub = esub + 1; 639*9880d681SAndroid Build Coastguard Worker esub += OPND(m->g->strip[esub]); 640*9880d681SAndroid Build Coastguard Worker if (OP(m->g->strip[esub]) == OOR2) 641*9880d681SAndroid Build Coastguard Worker esub--; 642*9880d681SAndroid Build Coastguard Worker else 643*9880d681SAndroid Build Coastguard Worker assert(OP(m->g->strip[esub]) == O_CH); 644*9880d681SAndroid Build Coastguard Worker } 645*9880d681SAndroid Build Coastguard Worker break; 646*9880d681SAndroid Build Coastguard Worker case OLPAREN: /* must undo assignment if rest fails */ 647*9880d681SAndroid Build Coastguard Worker i = OPND(s); 648*9880d681SAndroid Build Coastguard Worker assert(0 < i && i <= m->g->nsub); 649*9880d681SAndroid Build Coastguard Worker offsave = m->pmatch[i].rm_so; 650*9880d681SAndroid Build Coastguard Worker m->pmatch[i].rm_so = sp - m->offp; 651*9880d681SAndroid Build Coastguard Worker dp = backref(m, sp, stop, ss+1, stopst, lev, rec); 652*9880d681SAndroid Build Coastguard Worker if (dp != NULL) 653*9880d681SAndroid Build Coastguard Worker return(dp); 654*9880d681SAndroid Build Coastguard Worker m->pmatch[i].rm_so = offsave; 655*9880d681SAndroid Build Coastguard Worker return(NULL); 656*9880d681SAndroid Build Coastguard Worker break; 657*9880d681SAndroid Build Coastguard Worker case ORPAREN: /* must undo assignment if rest fails */ 658*9880d681SAndroid Build Coastguard Worker i = OPND(s); 659*9880d681SAndroid Build Coastguard Worker assert(0 < i && i <= m->g->nsub); 660*9880d681SAndroid Build Coastguard Worker offsave = m->pmatch[i].rm_eo; 661*9880d681SAndroid Build Coastguard Worker m->pmatch[i].rm_eo = sp - m->offp; 662*9880d681SAndroid Build Coastguard Worker dp = backref(m, sp, stop, ss+1, stopst, lev, rec); 663*9880d681SAndroid Build Coastguard Worker if (dp != NULL) 664*9880d681SAndroid Build Coastguard Worker return(dp); 665*9880d681SAndroid Build Coastguard Worker m->pmatch[i].rm_eo = offsave; 666*9880d681SAndroid Build Coastguard Worker return(NULL); 667*9880d681SAndroid Build Coastguard Worker break; 668*9880d681SAndroid Build Coastguard Worker default: /* uh oh */ 669*9880d681SAndroid Build Coastguard Worker assert(nope); 670*9880d681SAndroid Build Coastguard Worker break; 671*9880d681SAndroid Build Coastguard Worker } 672*9880d681SAndroid Build Coastguard Worker 673*9880d681SAndroid Build Coastguard Worker /* "can't happen" */ 674*9880d681SAndroid Build Coastguard Worker assert(nope); 675*9880d681SAndroid Build Coastguard Worker /* NOTREACHED */ 676*9880d681SAndroid Build Coastguard Worker return NULL; 677*9880d681SAndroid Build Coastguard Worker} 678*9880d681SAndroid Build Coastguard Worker 679*9880d681SAndroid Build Coastguard Worker/* 680*9880d681SAndroid Build Coastguard Worker - fast - step through the string at top speed 681*9880d681SAndroid Build Coastguard Worker */ 682*9880d681SAndroid Build Coastguard Workerstatic const char * /* where tentative match ended, or NULL */ 683*9880d681SAndroid Build Coastguard Workerfast(struct match *m, const char *start, const char *stop, sopno startst, 684*9880d681SAndroid Build Coastguard Worker sopno stopst) 685*9880d681SAndroid Build Coastguard Worker{ 686*9880d681SAndroid Build Coastguard Worker states st = m->st; 687*9880d681SAndroid Build Coastguard Worker states fresh = m->fresh; 688*9880d681SAndroid Build Coastguard Worker states tmp = m->tmp; 689*9880d681SAndroid Build Coastguard Worker const char *p = start; 690*9880d681SAndroid Build Coastguard Worker int c = (start == m->beginp) ? OUT : *(start-1); 691*9880d681SAndroid Build Coastguard Worker int lastc; /* previous c */ 692*9880d681SAndroid Build Coastguard Worker int flagch; 693*9880d681SAndroid Build Coastguard Worker int i; 694*9880d681SAndroid Build Coastguard Worker const char *coldp; /* last p after which no match was underway */ 695*9880d681SAndroid Build Coastguard Worker 696*9880d681SAndroid Build Coastguard Worker CLEAR(st); 697*9880d681SAndroid Build Coastguard Worker SET1(st, startst); 698*9880d681SAndroid Build Coastguard Worker st = step(m->g, startst, stopst, st, NOTHING, st); 699*9880d681SAndroid Build Coastguard Worker ASSIGN(fresh, st); 700*9880d681SAndroid Build Coastguard Worker SP("start", st, *p); 701*9880d681SAndroid Build Coastguard Worker coldp = NULL; 702*9880d681SAndroid Build Coastguard Worker for (;;) { 703*9880d681SAndroid Build Coastguard Worker /* next character */ 704*9880d681SAndroid Build Coastguard Worker lastc = c; 705*9880d681SAndroid Build Coastguard Worker c = (p == m->endp) ? OUT : *p; 706*9880d681SAndroid Build Coastguard Worker if (EQ(st, fresh)) 707*9880d681SAndroid Build Coastguard Worker coldp = p; 708*9880d681SAndroid Build Coastguard Worker 709*9880d681SAndroid Build Coastguard Worker /* is there an EOL and/or BOL between lastc and c? */ 710*9880d681SAndroid Build Coastguard Worker flagch = '\0'; 711*9880d681SAndroid Build Coastguard Worker i = 0; 712*9880d681SAndroid Build Coastguard Worker if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || 713*9880d681SAndroid Build Coastguard Worker (lastc == OUT && !(m->eflags®_NOTBOL)) ) { 714*9880d681SAndroid Build Coastguard Worker flagch = BOL; 715*9880d681SAndroid Build Coastguard Worker i = m->g->nbol; 716*9880d681SAndroid Build Coastguard Worker } 717*9880d681SAndroid Build Coastguard Worker if ( (c == '\n' && m->g->cflags®_NEWLINE) || 718*9880d681SAndroid Build Coastguard Worker (c == OUT && !(m->eflags®_NOTEOL)) ) { 719*9880d681SAndroid Build Coastguard Worker flagch = (flagch == BOL) ? BOLEOL : EOL; 720*9880d681SAndroid Build Coastguard Worker i += m->g->neol; 721*9880d681SAndroid Build Coastguard Worker } 722*9880d681SAndroid Build Coastguard Worker if (i != 0) { 723*9880d681SAndroid Build Coastguard Worker for (; i > 0; i--) 724*9880d681SAndroid Build Coastguard Worker st = step(m->g, startst, stopst, st, flagch, st); 725*9880d681SAndroid Build Coastguard Worker SP("boleol", st, c); 726*9880d681SAndroid Build Coastguard Worker } 727*9880d681SAndroid Build Coastguard Worker 728*9880d681SAndroid Build Coastguard Worker /* how about a word boundary? */ 729*9880d681SAndroid Build Coastguard Worker if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && 730*9880d681SAndroid Build Coastguard Worker (c != OUT && ISWORD(c)) ) { 731*9880d681SAndroid Build Coastguard Worker flagch = BOW; 732*9880d681SAndroid Build Coastguard Worker } 733*9880d681SAndroid Build Coastguard Worker if ( (lastc != OUT && ISWORD(lastc)) && 734*9880d681SAndroid Build Coastguard Worker (flagch == EOL || (c != OUT && !ISWORD(c))) ) { 735*9880d681SAndroid Build Coastguard Worker flagch = EOW; 736*9880d681SAndroid Build Coastguard Worker } 737*9880d681SAndroid Build Coastguard Worker if (flagch == BOW || flagch == EOW) { 738*9880d681SAndroid Build Coastguard Worker st = step(m->g, startst, stopst, st, flagch, st); 739*9880d681SAndroid Build Coastguard Worker SP("boweow", st, c); 740*9880d681SAndroid Build Coastguard Worker } 741*9880d681SAndroid Build Coastguard Worker 742*9880d681SAndroid Build Coastguard Worker /* are we done? */ 743*9880d681SAndroid Build Coastguard Worker if (ISSET(st, stopst) || p == stop) 744*9880d681SAndroid Build Coastguard Worker break; /* NOTE BREAK OUT */ 745*9880d681SAndroid Build Coastguard Worker 746*9880d681SAndroid Build Coastguard Worker /* no, we must deal with this character */ 747*9880d681SAndroid Build Coastguard Worker ASSIGN(tmp, st); 748*9880d681SAndroid Build Coastguard Worker ASSIGN(st, fresh); 749*9880d681SAndroid Build Coastguard Worker assert(c != OUT); 750*9880d681SAndroid Build Coastguard Worker st = step(m->g, startst, stopst, tmp, c, st); 751*9880d681SAndroid Build Coastguard Worker SP("aft", st, c); 752*9880d681SAndroid Build Coastguard Worker assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); 753*9880d681SAndroid Build Coastguard Worker p++; 754*9880d681SAndroid Build Coastguard Worker } 755*9880d681SAndroid Build Coastguard Worker 756*9880d681SAndroid Build Coastguard Worker assert(coldp != NULL); 757*9880d681SAndroid Build Coastguard Worker m->coldp = coldp; 758*9880d681SAndroid Build Coastguard Worker if (ISSET(st, stopst)) 759*9880d681SAndroid Build Coastguard Worker return(p+1); 760*9880d681SAndroid Build Coastguard Worker else 761*9880d681SAndroid Build Coastguard Worker return(NULL); 762*9880d681SAndroid Build Coastguard Worker} 763*9880d681SAndroid Build Coastguard Worker 764*9880d681SAndroid Build Coastguard Worker/* 765*9880d681SAndroid Build Coastguard Worker - slow - step through the string more deliberately 766*9880d681SAndroid Build Coastguard Worker */ 767*9880d681SAndroid Build Coastguard Workerstatic const char * /* where it ended */ 768*9880d681SAndroid Build Coastguard Workerslow(struct match *m, const char *start, const char *stop, sopno startst, 769*9880d681SAndroid Build Coastguard Worker sopno stopst) 770*9880d681SAndroid Build Coastguard Worker{ 771*9880d681SAndroid Build Coastguard Worker states st = m->st; 772*9880d681SAndroid Build Coastguard Worker states empty = m->empty; 773*9880d681SAndroid Build Coastguard Worker states tmp = m->tmp; 774*9880d681SAndroid Build Coastguard Worker const char *p = start; 775*9880d681SAndroid Build Coastguard Worker int c = (start == m->beginp) ? OUT : *(start-1); 776*9880d681SAndroid Build Coastguard Worker int lastc; /* previous c */ 777*9880d681SAndroid Build Coastguard Worker int flagch; 778*9880d681SAndroid Build Coastguard Worker int i; 779*9880d681SAndroid Build Coastguard Worker const char *matchp; /* last p at which a match ended */ 780*9880d681SAndroid Build Coastguard Worker 781*9880d681SAndroid Build Coastguard Worker AT("slow", start, stop, startst, stopst); 782*9880d681SAndroid Build Coastguard Worker CLEAR(st); 783*9880d681SAndroid Build Coastguard Worker SET1(st, startst); 784*9880d681SAndroid Build Coastguard Worker SP("sstart", st, *p); 785*9880d681SAndroid Build Coastguard Worker st = step(m->g, startst, stopst, st, NOTHING, st); 786*9880d681SAndroid Build Coastguard Worker matchp = NULL; 787*9880d681SAndroid Build Coastguard Worker for (;;) { 788*9880d681SAndroid Build Coastguard Worker /* next character */ 789*9880d681SAndroid Build Coastguard Worker lastc = c; 790*9880d681SAndroid Build Coastguard Worker c = (p == m->endp) ? OUT : *p; 791*9880d681SAndroid Build Coastguard Worker 792*9880d681SAndroid Build Coastguard Worker /* is there an EOL and/or BOL between lastc and c? */ 793*9880d681SAndroid Build Coastguard Worker flagch = '\0'; 794*9880d681SAndroid Build Coastguard Worker i = 0; 795*9880d681SAndroid Build Coastguard Worker if ( (lastc == '\n' && m->g->cflags®_NEWLINE) || 796*9880d681SAndroid Build Coastguard Worker (lastc == OUT && !(m->eflags®_NOTBOL)) ) { 797*9880d681SAndroid Build Coastguard Worker flagch = BOL; 798*9880d681SAndroid Build Coastguard Worker i = m->g->nbol; 799*9880d681SAndroid Build Coastguard Worker } 800*9880d681SAndroid Build Coastguard Worker if ( (c == '\n' && m->g->cflags®_NEWLINE) || 801*9880d681SAndroid Build Coastguard Worker (c == OUT && !(m->eflags®_NOTEOL)) ) { 802*9880d681SAndroid Build Coastguard Worker flagch = (flagch == BOL) ? BOLEOL : EOL; 803*9880d681SAndroid Build Coastguard Worker i += m->g->neol; 804*9880d681SAndroid Build Coastguard Worker } 805*9880d681SAndroid Build Coastguard Worker if (i != 0) { 806*9880d681SAndroid Build Coastguard Worker for (; i > 0; i--) 807*9880d681SAndroid Build Coastguard Worker st = step(m->g, startst, stopst, st, flagch, st); 808*9880d681SAndroid Build Coastguard Worker SP("sboleol", st, c); 809*9880d681SAndroid Build Coastguard Worker } 810*9880d681SAndroid Build Coastguard Worker 811*9880d681SAndroid Build Coastguard Worker /* how about a word boundary? */ 812*9880d681SAndroid Build Coastguard Worker if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) && 813*9880d681SAndroid Build Coastguard Worker (c != OUT && ISWORD(c)) ) { 814*9880d681SAndroid Build Coastguard Worker flagch = BOW; 815*9880d681SAndroid Build Coastguard Worker } 816*9880d681SAndroid Build Coastguard Worker if ( (lastc != OUT && ISWORD(lastc)) && 817*9880d681SAndroid Build Coastguard Worker (flagch == EOL || (c != OUT && !ISWORD(c))) ) { 818*9880d681SAndroid Build Coastguard Worker flagch = EOW; 819*9880d681SAndroid Build Coastguard Worker } 820*9880d681SAndroid Build Coastguard Worker if (flagch == BOW || flagch == EOW) { 821*9880d681SAndroid Build Coastguard Worker st = step(m->g, startst, stopst, st, flagch, st); 822*9880d681SAndroid Build Coastguard Worker SP("sboweow", st, c); 823*9880d681SAndroid Build Coastguard Worker } 824*9880d681SAndroid Build Coastguard Worker 825*9880d681SAndroid Build Coastguard Worker /* are we done? */ 826*9880d681SAndroid Build Coastguard Worker if (ISSET(st, stopst)) 827*9880d681SAndroid Build Coastguard Worker matchp = p; 828*9880d681SAndroid Build Coastguard Worker if (EQ(st, empty) || p == stop) 829*9880d681SAndroid Build Coastguard Worker break; /* NOTE BREAK OUT */ 830*9880d681SAndroid Build Coastguard Worker 831*9880d681SAndroid Build Coastguard Worker /* no, we must deal with this character */ 832*9880d681SAndroid Build Coastguard Worker ASSIGN(tmp, st); 833*9880d681SAndroid Build Coastguard Worker ASSIGN(st, empty); 834*9880d681SAndroid Build Coastguard Worker assert(c != OUT); 835*9880d681SAndroid Build Coastguard Worker st = step(m->g, startst, stopst, tmp, c, st); 836*9880d681SAndroid Build Coastguard Worker SP("saft", st, c); 837*9880d681SAndroid Build Coastguard Worker assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st)); 838*9880d681SAndroid Build Coastguard Worker p++; 839*9880d681SAndroid Build Coastguard Worker } 840*9880d681SAndroid Build Coastguard Worker 841*9880d681SAndroid Build Coastguard Worker return(matchp); 842*9880d681SAndroid Build Coastguard Worker} 843*9880d681SAndroid Build Coastguard Worker 844*9880d681SAndroid Build Coastguard Worker 845*9880d681SAndroid Build Coastguard Worker/* 846*9880d681SAndroid Build Coastguard Worker - step - map set of states reachable before char to set reachable after 847*9880d681SAndroid Build Coastguard Worker */ 848*9880d681SAndroid Build Coastguard Workerstatic states 849*9880d681SAndroid Build Coastguard Workerstep(struct re_guts *g, 850*9880d681SAndroid Build Coastguard Worker sopno start, /* start state within strip */ 851*9880d681SAndroid Build Coastguard Worker sopno stop, /* state after stop state within strip */ 852*9880d681SAndroid Build Coastguard Worker states bef, /* states reachable before */ 853*9880d681SAndroid Build Coastguard Worker int ch, /* character or NONCHAR code */ 854*9880d681SAndroid Build Coastguard Worker states aft) /* states already known reachable after */ 855*9880d681SAndroid Build Coastguard Worker{ 856*9880d681SAndroid Build Coastguard Worker cset *cs; 857*9880d681SAndroid Build Coastguard Worker sop s; 858*9880d681SAndroid Build Coastguard Worker sopno pc; 859*9880d681SAndroid Build Coastguard Worker onestate here; /* note, macros know this name */ 860*9880d681SAndroid Build Coastguard Worker sopno look; 861*9880d681SAndroid Build Coastguard Worker int i; 862*9880d681SAndroid Build Coastguard Worker 863*9880d681SAndroid Build Coastguard Worker for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) { 864*9880d681SAndroid Build Coastguard Worker s = g->strip[pc]; 865*9880d681SAndroid Build Coastguard Worker switch (OP(s)) { 866*9880d681SAndroid Build Coastguard Worker case OEND: 867*9880d681SAndroid Build Coastguard Worker assert(pc == stop-1); 868*9880d681SAndroid Build Coastguard Worker break; 869*9880d681SAndroid Build Coastguard Worker case OCHAR: 870*9880d681SAndroid Build Coastguard Worker /* only characters can match */ 871*9880d681SAndroid Build Coastguard Worker assert(!NONCHAR(ch) || ch != (char)OPND(s)); 872*9880d681SAndroid Build Coastguard Worker if (ch == (char)OPND(s)) 873*9880d681SAndroid Build Coastguard Worker FWD(aft, bef, 1); 874*9880d681SAndroid Build Coastguard Worker break; 875*9880d681SAndroid Build Coastguard Worker case OBOL: 876*9880d681SAndroid Build Coastguard Worker if (ch == BOL || ch == BOLEOL) 877*9880d681SAndroid Build Coastguard Worker FWD(aft, bef, 1); 878*9880d681SAndroid Build Coastguard Worker break; 879*9880d681SAndroid Build Coastguard Worker case OEOL: 880*9880d681SAndroid Build Coastguard Worker if (ch == EOL || ch == BOLEOL) 881*9880d681SAndroid Build Coastguard Worker FWD(aft, bef, 1); 882*9880d681SAndroid Build Coastguard Worker break; 883*9880d681SAndroid Build Coastguard Worker case OBOW: 884*9880d681SAndroid Build Coastguard Worker if (ch == BOW) 885*9880d681SAndroid Build Coastguard Worker FWD(aft, bef, 1); 886*9880d681SAndroid Build Coastguard Worker break; 887*9880d681SAndroid Build Coastguard Worker case OEOW: 888*9880d681SAndroid Build Coastguard Worker if (ch == EOW) 889*9880d681SAndroid Build Coastguard Worker FWD(aft, bef, 1); 890*9880d681SAndroid Build Coastguard Worker break; 891*9880d681SAndroid Build Coastguard Worker case OANY: 892*9880d681SAndroid Build Coastguard Worker if (!NONCHAR(ch)) 893*9880d681SAndroid Build Coastguard Worker FWD(aft, bef, 1); 894*9880d681SAndroid Build Coastguard Worker break; 895*9880d681SAndroid Build Coastguard Worker case OANYOF: 896*9880d681SAndroid Build Coastguard Worker cs = &g->sets[OPND(s)]; 897*9880d681SAndroid Build Coastguard Worker if (!NONCHAR(ch) && CHIN(cs, ch)) 898*9880d681SAndroid Build Coastguard Worker FWD(aft, bef, 1); 899*9880d681SAndroid Build Coastguard Worker break; 900*9880d681SAndroid Build Coastguard Worker case OBACK_: /* ignored here */ 901*9880d681SAndroid Build Coastguard Worker case O_BACK: 902*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, 1); 903*9880d681SAndroid Build Coastguard Worker break; 904*9880d681SAndroid Build Coastguard Worker case OPLUS_: /* forward, this is just an empty */ 905*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, 1); 906*9880d681SAndroid Build Coastguard Worker break; 907*9880d681SAndroid Build Coastguard Worker case O_PLUS: /* both forward and back */ 908*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, 1); 909*9880d681SAndroid Build Coastguard Worker i = ISSETBACK(aft, OPND(s)); 910*9880d681SAndroid Build Coastguard Worker BACK(aft, aft, OPND(s)); 911*9880d681SAndroid Build Coastguard Worker if (!i && ISSETBACK(aft, OPND(s))) { 912*9880d681SAndroid Build Coastguard Worker /* oho, must reconsider loop body */ 913*9880d681SAndroid Build Coastguard Worker pc -= OPND(s) + 1; 914*9880d681SAndroid Build Coastguard Worker INIT(here, pc); 915*9880d681SAndroid Build Coastguard Worker } 916*9880d681SAndroid Build Coastguard Worker break; 917*9880d681SAndroid Build Coastguard Worker case OQUEST_: /* two branches, both forward */ 918*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, 1); 919*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, OPND(s)); 920*9880d681SAndroid Build Coastguard Worker break; 921*9880d681SAndroid Build Coastguard Worker case O_QUEST: /* just an empty */ 922*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, 1); 923*9880d681SAndroid Build Coastguard Worker break; 924*9880d681SAndroid Build Coastguard Worker case OLPAREN: /* not significant here */ 925*9880d681SAndroid Build Coastguard Worker case ORPAREN: 926*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, 1); 927*9880d681SAndroid Build Coastguard Worker break; 928*9880d681SAndroid Build Coastguard Worker case OCH_: /* mark the first two branches */ 929*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, 1); 930*9880d681SAndroid Build Coastguard Worker assert(OP(g->strip[pc+OPND(s)]) == OOR2); 931*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, OPND(s)); 932*9880d681SAndroid Build Coastguard Worker break; 933*9880d681SAndroid Build Coastguard Worker case OOR1: /* done a branch, find the O_CH */ 934*9880d681SAndroid Build Coastguard Worker if (ISSTATEIN(aft, here)) { 935*9880d681SAndroid Build Coastguard Worker for (look = 1; 936*9880d681SAndroid Build Coastguard Worker OP(s = g->strip[pc+look]) != O_CH; 937*9880d681SAndroid Build Coastguard Worker look += OPND(s)) 938*9880d681SAndroid Build Coastguard Worker assert(OP(s) == OOR2); 939*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, look); 940*9880d681SAndroid Build Coastguard Worker } 941*9880d681SAndroid Build Coastguard Worker break; 942*9880d681SAndroid Build Coastguard Worker case OOR2: /* propagate OCH_'s marking */ 943*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, 1); 944*9880d681SAndroid Build Coastguard Worker if (OP(g->strip[pc+OPND(s)]) != O_CH) { 945*9880d681SAndroid Build Coastguard Worker assert(OP(g->strip[pc+OPND(s)]) == OOR2); 946*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, OPND(s)); 947*9880d681SAndroid Build Coastguard Worker } 948*9880d681SAndroid Build Coastguard Worker break; 949*9880d681SAndroid Build Coastguard Worker case O_CH: /* just empty */ 950*9880d681SAndroid Build Coastguard Worker FWD(aft, aft, 1); 951*9880d681SAndroid Build Coastguard Worker break; 952*9880d681SAndroid Build Coastguard Worker default: /* ooooops... */ 953*9880d681SAndroid Build Coastguard Worker assert(nope); 954*9880d681SAndroid Build Coastguard Worker break; 955*9880d681SAndroid Build Coastguard Worker } 956*9880d681SAndroid Build Coastguard Worker } 957*9880d681SAndroid Build Coastguard Worker 958*9880d681SAndroid Build Coastguard Worker return(aft); 959*9880d681SAndroid Build Coastguard Worker} 960*9880d681SAndroid Build Coastguard Worker 961*9880d681SAndroid Build Coastguard Worker#ifdef REDEBUG 962*9880d681SAndroid Build Coastguard Worker/* 963*9880d681SAndroid Build Coastguard Worker - print - print a set of states 964*9880d681SAndroid Build Coastguard Worker */ 965*9880d681SAndroid Build Coastguard Workerstatic void 966*9880d681SAndroid Build Coastguard Workerprint(struct match *m, char *caption, states st, int ch, FILE *d) 967*9880d681SAndroid Build Coastguard Worker{ 968*9880d681SAndroid Build Coastguard Worker struct re_guts *g = m->g; 969*9880d681SAndroid Build Coastguard Worker int i; 970*9880d681SAndroid Build Coastguard Worker int first = 1; 971*9880d681SAndroid Build Coastguard Worker 972*9880d681SAndroid Build Coastguard Worker if (!(m->eflags®_TRACE)) 973*9880d681SAndroid Build Coastguard Worker return; 974*9880d681SAndroid Build Coastguard Worker 975*9880d681SAndroid Build Coastguard Worker (void)fprintf(d, "%s", caption); 976*9880d681SAndroid Build Coastguard Worker if (ch != '\0') 977*9880d681SAndroid Build Coastguard Worker (void)fprintf(d, " %s", pchar(ch)); 978*9880d681SAndroid Build Coastguard Worker for (i = 0; i < g->nstates; i++) 979*9880d681SAndroid Build Coastguard Worker if (ISSET(st, i)) { 980*9880d681SAndroid Build Coastguard Worker (void)fprintf(d, "%s%d", (first) ? "\t" : ", ", i); 981*9880d681SAndroid Build Coastguard Worker first = 0; 982*9880d681SAndroid Build Coastguard Worker } 983*9880d681SAndroid Build Coastguard Worker (void)fprintf(d, "\n"); 984*9880d681SAndroid Build Coastguard Worker} 985*9880d681SAndroid Build Coastguard Worker 986*9880d681SAndroid Build Coastguard Worker/* 987*9880d681SAndroid Build Coastguard Worker - at - print current situation 988*9880d681SAndroid Build Coastguard Worker */ 989*9880d681SAndroid Build Coastguard Workerstatic void 990*9880d681SAndroid Build Coastguard Workerat(struct match *m, char *title, char *start, char *stop, sopno startst, 991*9880d681SAndroid Build Coastguard Worker sopno stopst) 992*9880d681SAndroid Build Coastguard Worker{ 993*9880d681SAndroid Build Coastguard Worker if (!(m->eflags®_TRACE)) 994*9880d681SAndroid Build Coastguard Worker return; 995*9880d681SAndroid Build Coastguard Worker 996*9880d681SAndroid Build Coastguard Worker (void)printf("%s %s-", title, pchar(*start)); 997*9880d681SAndroid Build Coastguard Worker (void)printf("%s ", pchar(*stop)); 998*9880d681SAndroid Build Coastguard Worker (void)printf("%ld-%ld\n", (long)startst, (long)stopst); 999*9880d681SAndroid Build Coastguard Worker} 1000*9880d681SAndroid Build Coastguard Worker 1001*9880d681SAndroid Build Coastguard Worker#ifndef PCHARDONE 1002*9880d681SAndroid Build Coastguard Worker#define PCHARDONE /* never again */ 1003*9880d681SAndroid Build Coastguard Worker/* 1004*9880d681SAndroid Build Coastguard Worker - pchar - make a character printable 1005*9880d681SAndroid Build Coastguard Worker * 1006*9880d681SAndroid Build Coastguard Worker * Is this identical to regchar() over in debug.c? Well, yes. But a 1007*9880d681SAndroid Build Coastguard Worker * duplicate here avoids having a debugging-capable regexec.o tied to 1008*9880d681SAndroid Build Coastguard Worker * a matching debug.o, and this is convenient. It all disappears in 1009*9880d681SAndroid Build Coastguard Worker * the non-debug compilation anyway, so it doesn't matter much. 1010*9880d681SAndroid Build Coastguard Worker */ 1011*9880d681SAndroid Build Coastguard Workerstatic char * /* -> representation */ 1012*9880d681SAndroid Build Coastguard Workerpchar(int ch) 1013*9880d681SAndroid Build Coastguard Worker{ 1014*9880d681SAndroid Build Coastguard Worker static char pbuf[10]; 1015*9880d681SAndroid Build Coastguard Worker 1016*9880d681SAndroid Build Coastguard Worker if (isprint(ch) || ch == ' ') 1017*9880d681SAndroid Build Coastguard Worker (void)snprintf(pbuf, sizeof pbuf, "%c", ch); 1018*9880d681SAndroid Build Coastguard Worker else 1019*9880d681SAndroid Build Coastguard Worker (void)snprintf(pbuf, sizeof pbuf, "\\%o", ch); 1020*9880d681SAndroid Build Coastguard Worker return(pbuf); 1021*9880d681SAndroid Build Coastguard Worker} 1022*9880d681SAndroid Build Coastguard Worker#endif 1023*9880d681SAndroid Build Coastguard Worker#endif 1024*9880d681SAndroid Build Coastguard Worker 1025*9880d681SAndroid Build Coastguard Worker#undef matcher 1026*9880d681SAndroid Build Coastguard Worker#undef fast 1027*9880d681SAndroid Build Coastguard Worker#undef slow 1028*9880d681SAndroid Build Coastguard Worker#undef dissect 1029*9880d681SAndroid Build Coastguard Worker#undef backref 1030*9880d681SAndroid Build Coastguard Worker#undef step 1031*9880d681SAndroid Build Coastguard Worker#undef print 1032*9880d681SAndroid Build Coastguard Worker#undef at 1033*9880d681SAndroid Build Coastguard Worker#undef match 1034*9880d681SAndroid Build Coastguard Worker#undef nope 1035