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