1cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes/*	$NetBSD: engine.c,v 1.24 2012/03/13 21:13:42 christos Exp $	*/
24fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
34fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*-
44fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * Copyright (c) 1992, 1993, 1994
54fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *	The Regents of the University of California.  All rights reserved.
64fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *
74fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * This code is derived from software contributed to Berkeley by
84fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * Henry Spencer.
94fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *
104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * Redistribution and use in source and binary forms, with or without
114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * modification, are permitted provided that the following conditions
124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * are met:
134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * 1. Redistributions of source code must retain the above copyright
144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *    notice, this list of conditions and the following disclaimer.
154fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * 2. Redistributions in binary form must reproduce the above copyright
164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *    notice, this list of conditions and the following disclaimer in the
174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *    documentation and/or other materials provided with the distribution.
184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * 3. Neither the name of the University nor the names of its contributors
194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *    may be used to endorse or promote products derived from this software
204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *    without specific prior written permission.
214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *
224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
234fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
244fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
254fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
264fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
294fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
304fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
324fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * SUCH DAMAGE.
334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *
344fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *	@(#)engine.c	8.5 (Berkeley) 3/20/94
354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
37cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes/*-
38cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * Copyright (c) 1992, 1993, 1994 Henry Spencer.
39cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *
40cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * This code is derived from software contributed to Berkeley by
41cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * Henry Spencer.
42cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *
43cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * Redistribution and use in source and binary forms, with or without
44cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * modification, are permitted provided that the following conditions
45cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * are met:
46cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * 1. Redistributions of source code must retain the above copyright
47cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *    notice, this list of conditions and the following disclaimer.
48cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * 2. Redistributions in binary form must reproduce the above copyright
49cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *    notice, this list of conditions and the following disclaimer in the
50cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *    documentation and/or other materials provided with the distribution.
51cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * 3. All advertising materials mentioning features or use of this software
52cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *    must display the following acknowledgement:
53cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *	This product includes software developed by the University of
54cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *	California, Berkeley and its contributors.
55cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * 4. Neither the name of the University nor the names of its contributors
56cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *    may be used to endorse or promote products derived from this software
57cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *    without specific prior written permission.
58cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *
59cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes * SUCH DAMAGE.
70cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *
71cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes *	@(#)engine.c	8.5 (Berkeley) 3/20/94
72cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes */
73cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
744fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
754fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * The matching engine and friends.  This file is #included by regexec.c
764fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * after suitable #defines of a variety of macros used herein, so that
774fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * different state representations can be used without duplicating masses
784fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * of code.
794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#ifdef SNAMES
824fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	matcher	smatcher
834fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	fast	sfast
844fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	slow	sslow
854fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	dissect	sdissect
864fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	backref	sbackref
874fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	step	sstep
884fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	print	sprint
894fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	at	sat
904fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	match	smat
914fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	nope	snope
924fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#endif
934fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#ifdef LNAMES
944fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	matcher	lmatcher
954fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	fast	lfast
964fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	slow	lslow
974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	dissect	ldissect
984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	backref	lbackref
994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	step	lstep
1004fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	print	lprint
1014fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	at	lat
1024fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	match	lmat
1034fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	nope	lnope
1044fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#endif
1054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
1064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/* another structure passed up and down to avoid zillions of parameters */
1074fa7b105644222d9b35347c9d226ca8e011072ebColin Crossstruct match {
1084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	struct re_guts *g;
1094fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int eflags;
1104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	regmatch_t *pmatch;	/* [nsub+1] (0 element unused) */
111cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *offp;	/* offsets work from here */
112cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *beginp;	/* start of string -- virtual NUL precedes */
113cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *endp;	/* end of string -- virtual NUL here */
114cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *coldp;	/* can be no match starting before here */
115cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char **lastpos;	/* [nplus+1] */
1164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	STATEVARS;
1174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states st;		/* current states */
1184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states fresh;		/* states for a fresh start */
1194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states tmp;		/* temporary */
1204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states empty;		/* empty set of states */
1214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross};
1224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
123cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes/* ========= begin header generated by ./mkh ========= */
124cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#ifdef __cplusplus
125cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesextern "C" {
126cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#endif
127cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
128cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes/* === engine.c === */
129cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic int matcher(struct re_guts *g, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
130cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic const char *dissect(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
131cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic const char *backref(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst, sopno lev);
132cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic const char *fast(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
133cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic const char *slow(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
134cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic states step(struct re_guts *g, sopno start, sopno stop, states bef, int ch, states aft);
1354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	BOL	(OUT+1)
1364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	EOL	(BOL+1)
1374fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	BOLEOL	(BOL+2)
1384fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	NOTHING	(BOL+3)
1394fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	BOW	(BOL+4)
1404fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	EOW	(BOL+5)
1414fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	CODEMAX	(BOL+5)		/* highest code used */
1424fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	NONCHAR(c)	((c) > CHAR_MAX)
1434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	NNONCHAR	(CODEMAX-CHAR_MAX)
1444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#ifdef REDEBUG
145cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic void print(struct match *m, char *caption, states st, int ch, FILE *d);
1464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#endif
1474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#ifdef REDEBUG
148cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic void at(struct match *m, char *title, char *start, char *stop, sopno startst, sopno stopst);
1494fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#endif
1504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#ifdef REDEBUG
151cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic char *pchar(int ch);
152cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#endif
153cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
154cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#ifdef __cplusplus
155cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes}
1564fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#endif
157cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes/* ========= end header generated by ./mkh ========= */
1584fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
1594fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#ifdef REDEBUG
1604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	SP(t, s, c)	print(m, t, s, c, stdout)
1614fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	AT(t, p1, p2, s1, s2)	at(m, t, p1, p2, s1, s2)
162cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#define	NOTE(str)	{ if (m->eflags&REG_TRACE) printf("=%s\n", (str)); }
1634fa7b105644222d9b35347c9d226ca8e011072ebColin Crossstatic int nope = 0;
1644fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#else
1654fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	SP(t, s, c)	/* nothing */
1664fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	AT(t, p1, p2, s1, s2)	/* nothing */
1674fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	NOTE(s)	/* nothing */
1684fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#endif
1694fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
1704fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
1714fa7b105644222d9b35347c9d226ca8e011072ebColin Cross - matcher - the actual matching engine
172cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == static int matcher(struct re_guts *g, char *string, \
173cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes ==	size_t nmatch, regmatch_t pmatch[], int eflags);
1744fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
1754fa7b105644222d9b35347c9d226ca8e011072ebColin Crossstatic int			/* 0 success, REG_NOMATCH failure */
176cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesmatcher(
177cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    struct re_guts *g,
178cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    const char *string,
179cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    size_t nmatch,
180cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    regmatch_t pmatch[],
1814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross    int eflags)
1824fa7b105644222d9b35347c9d226ca8e011072ebColin Cross{
183cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *endp;
184cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	size_t i;
1854fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	struct match mv;
1864fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	struct match *m = &mv;
187cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *dp;
1884fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	const sopno gf = g->firststate+1;	/* +1 for OEND */
1894fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	const sopno gl = g->laststate;
190cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *start;
191cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *stop;
192cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	int error = 0;
193cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
194cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(g != NULL);
195cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(string != NULL);
196cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	/* pmatch checked below */
1974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
1984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	/* simplify the situation where possible */
1994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (g->cflags&REG_NOSUB)
2004fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		nmatch = 0;
2014fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (eflags&REG_STARTEND) {
202cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		_DIAGASSERT(pmatch != NULL);
203cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		start = string + (size_t)pmatch[0].rm_so;
204cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		stop = string + (size_t)pmatch[0].rm_eo;
2054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	} else {
2064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		start = string;
2074fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		stop = start + strlen(start);
2084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
2094fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (stop < start)
2104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		return(REG_INVARG);
2114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
2124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	/* prescreening; this does wonders for this rather slow code */
2134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (g->must != NULL) {
2144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		for (dp = start; dp < stop; dp++)
215cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			if (*dp == g->must[0] && (size_t)(stop - dp) >= g->mlen &&
216cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				memcmp(dp, g->must, g->mlen) == 0)
2174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				break;
2184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (dp == stop)		/* we didn't find g->must */
2194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			return(REG_NOMATCH);
2204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
2214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
2224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	/* match struct setup */
2234fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	m->g = g;
2244fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	m->eflags = eflags;
2254fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	m->pmatch = NULL;
2264fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	m->lastpos = NULL;
2274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	m->offp = string;
2284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	m->beginp = start;
2294fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	m->endp = stop;
2304fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	STATESETUP(m, 4);
2314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	SETUP(m->st);
2324fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	SETUP(m->fresh);
2334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	SETUP(m->tmp);
2344fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	SETUP(m->empty);
2354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	CLEAR(m->empty);
2364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
2374fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	/* this loop does only one repetition except for backrefs */
2384fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	for (;;) {
2394fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		endp = fast(m, start, stop, gf, gl);
2404fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (endp == NULL) {		/* a miss */
241cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			error = REG_NOMATCH;
242cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			goto done;
2434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
2444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (nmatch == 0 && !g->backrefs)
2454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;		/* no further info needed */
2464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
2474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* where? */
2484fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(m->coldp != NULL);
2494fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		for (;;) {
2504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			NOTE("finding start");
2514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			endp = slow(m, m->coldp, stop, gf, gl);
2524fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (endp != NULL)
2534fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				break;
2544fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(m->coldp < m->endp);
2554fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			m->coldp++;
2564fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
2574fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (nmatch == 1 && !g->backrefs)
2584fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;		/* no further info needed */
2594fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
2604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* oh my, he wants the subexpressions... */
2614fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (m->pmatch == NULL)
2624fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) *
2634fa7b105644222d9b35347c9d226ca8e011072ebColin Cross							sizeof(regmatch_t));
2644fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (m->pmatch == NULL) {
265cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			error = REG_ESPACE;
266cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			goto done;
2674fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
268cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		for (i = 1; i <= m->g->nsub; i++)
269cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			m->pmatch[i].rm_so = m->pmatch[i].rm_eo = (regoff_t)-1;
2704fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (!g->backrefs && !(m->eflags&REG_BACKR)) {
2714fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			NOTE("dissecting");
2724fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			dp = dissect(m, m->coldp, endp, gf, gl);
2734fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		} else {
2744fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (g->nplus > 0 && m->lastpos == NULL)
275cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				m->lastpos = malloc((g->nplus+1) *
276cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes							sizeof(const char *));
2774fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (g->nplus > 0 && m->lastpos == NULL) {
278cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				error = REG_ESPACE;
279cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				goto done;
2804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
2814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			NOTE("backref dissect");
282cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
2834fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
2844fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (dp != NULL)
2854fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
2864fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
2874fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* uh-oh... we couldn't find a subexpression-level match */
2884fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(g->backrefs);	/* must be back references doing it */
2894fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(g->nplus == 0 || m->lastpos != NULL);
2904fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		for (;;) {
2914fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (dp != NULL || endp <= m->coldp)
2924fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				break;		/* defeat */
2934fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			NOTE("backoff");
2944fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			endp = slow(m, m->coldp, endp-1, gf, gl);
2954fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (endp == NULL)
2964fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				break;		/* defeat */
2974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			/* try it on a shorter possibility */
2984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#ifndef NDEBUG
2994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			for (i = 1; i <= m->g->nsub; i++) {
300cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				assert(m->pmatch[i].rm_so == (regoff_t)-1);
301cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				assert(m->pmatch[i].rm_eo == (regoff_t)-1);
3024fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
3034fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#endif
3044fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			NOTE("backoff dissect");
305cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
3064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
3074fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(dp == NULL || dp == endp);
3084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (dp != NULL)		/* found a shorter one */
3094fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
3104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
3114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* despite initial appearances, there is no match here */
3124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		NOTE("false alarm");
3134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		start = m->coldp + 1;	/* recycle starting later */
314cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		assert(start <= stop);
3154fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
3164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
3174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	/* fill in the details if requested */
3184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (nmatch > 0) {
319cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		_DIAGASSERT(pmatch != NULL);
3204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		pmatch[0].rm_so = m->coldp - m->offp;
3214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		pmatch[0].rm_eo = endp - m->offp;
3224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
3234fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (nmatch > 1) {
3244fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(m->pmatch != NULL);
325cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		for (i = 1; i < nmatch; i++)
326cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			if (i <= m->g->nsub)
3274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				pmatch[i] = m->pmatch[i];
3284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			else {
329cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				pmatch[i].rm_so = (regoff_t)-1;
330cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				pmatch[i].rm_eo = (regoff_t)-1;
3314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
3324fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
3334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
334cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesdone:
335cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	if (m->pmatch != NULL) {
336cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		free(m->pmatch);
337cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		m->pmatch = NULL;
338cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	}
339cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	if (m->lastpos != NULL) {
340cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		free(m->lastpos);
341cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		m->lastpos = NULL;
342cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	}
3434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	STATETEARDOWN(m);
344cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	return error;
3454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross}
3464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
3474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
3484fa7b105644222d9b35347c9d226ca8e011072ebColin Cross - dissect - figure out what matched what, no back references
349cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == static const char *dissect(struct match *m, const char *start, \
350cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes ==	const char *stop, sopno startst, sopno stopst);
3514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
352cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic const char *			/* == stop (success) always */
353cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesdissect(
354cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    struct match *m,
355cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    const char *start,
356cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    const char *stop,
357cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno startst,
358cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno stopst)
3594fa7b105644222d9b35347c9d226ca8e011072ebColin Cross{
3604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int i;
3614fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sopno ss;	/* start sop of current subRE */
3624fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sopno es;	/* end sop of current subRE */
363cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *sp;	/* start of string matched by it */
364cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *stp; /* string matched by it cannot pass here */
365cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *rest; /* start of rest of string */
366cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *tail; /* string unmatched by rest of RE */
3674fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sopno ssub;	/* start sop of subsubRE */
3684fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sopno esub;	/* end sop of subsubRE */
369cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *ssp; /* start of string matched by subsubRE */
370cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *sep; /* end of string matched by subsubRE */
371cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *oldssp; /* previous ssp */
372cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#ifndef NDEBUG
373cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *dp;
374cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#endif
375cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
376cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(m != NULL);
377cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(start != NULL);
378cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(stop != NULL);
3794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
3804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	AT("diss", start, stop, startst, stopst);
3814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sp = start;
3824fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	for (ss = startst; ss < stopst; ss = es) {
3834fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* identify end of subRE */
3844fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		es = ss;
3854fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		switch (OP(m->g->strip[es])) {
3864fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OPLUS_:
3874fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OQUEST_:
3884fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			es += OPND(m->g->strip[es]);
3894fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
3904fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OCH_:
3914fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			while (OP(m->g->strip[es]) != O_CH)
3924fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				es += OPND(m->g->strip[es]);
3934fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
3944fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
3954fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		es++;
3964fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
3974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* figure out what it matched */
3984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		switch (OP(m->g->strip[ss])) {
3994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OEND:
4004fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(nope);
4014fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
4024fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OCHAR:
4034fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			sp++;
4044fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
4054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OBOL:
4064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OEOL:
4074fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OBOW:
4084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OEOW:
4094fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
4104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OANY:
4114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OANYOF:
4124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			sp++;
4134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
4144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OBACK_:
4154fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case O_BACK:
4164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(nope);
4174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
4184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* cases where length of match is hard to find */
4194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OQUEST_:
4204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			stp = stop;
4214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			for (;;) {
4224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* how long could this one be? */
4234fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				rest = slow(m, sp, stp, ss, es);
4244fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(rest != NULL);	/* it did match */
4254fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* could the rest match the rest? */
4264fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				tail = slow(m, rest, stop, es, stopst);
4274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				if (tail == stop)
4284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					break;		/* yes! */
4294fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* no -- try a shorter match for this one */
4304fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				stp = rest - 1;
4314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(stp >= sp);	/* it did work */
4324fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
4334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			ssub = ss + 1;
4344fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			esub = es - 1;
4354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			/* did innards match? */
4364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (slow(m, sp, rest, ssub, esub) != NULL) {
437cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#ifdef NDEBUG
438cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				(void)
439cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#else
440cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				dp =
441cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#endif
442cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes				    dissect(m, sp, rest, ssub, esub);
4434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(dp == rest);
4444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			} else		/* no */
4454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(sp == rest);
4464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			sp = rest;
4474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
4484fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OPLUS_:
4494fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			stp = stop;
4504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			for (;;) {
4514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* how long could this one be? */
4524fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				rest = slow(m, sp, stp, ss, es);
4534fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(rest != NULL);	/* it did match */
4544fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* could the rest match the rest? */
4554fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				tail = slow(m, rest, stop, es, stopst);
4564fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				if (tail == stop)
4574fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					break;		/* yes! */
4584fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* no -- try a shorter match for this one */
4594fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				stp = rest - 1;
4604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(stp >= sp);	/* it did work */
4614fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
4624fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			ssub = ss + 1;
4634fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			esub = es - 1;
4644fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			ssp = sp;
4654fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			oldssp = ssp;
4664fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			for (;;) {	/* find last match of innards */
4674fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				sep = slow(m, ssp, rest, ssub, esub);
4684fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				if (sep == NULL || sep == ssp)
4694fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					break;	/* failed or matched null */
4704fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				oldssp = ssp;	/* on to next try */
4714fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				ssp = sep;
4724fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
4734fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (sep == NULL) {
4744fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* last successful match */
4754fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				sep = ssp;
4764fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				ssp = oldssp;
4774fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
4784fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(sep == rest);	/* must exhaust substring */
4794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(slow(m, ssp, sep, ssub, esub) == rest);
480cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#ifdef NDEBUG
481cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			(void)
482cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#else
483cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			dp =
484cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#endif
485cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			    dissect(m, ssp, sep, ssub, esub);
4864fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(dp == sep);
4874fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			sp = rest;
4884fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
4894fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OCH_:
4904fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			stp = stop;
4914fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			for (;;) {
4924fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* how long could this one be? */
4934fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				rest = slow(m, sp, stp, ss, es);
4944fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(rest != NULL);	/* it did match */
4954fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* could the rest match the rest? */
4964fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				tail = slow(m, rest, stop, es, stopst);
4974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				if (tail == stop)
4984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					break;		/* yes! */
4994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* no -- try a shorter match for this one */
5004fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				stp = rest - 1;
5014fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(stp >= sp);	/* it did work */
5024fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
5034fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			ssub = ss + 1;
5044fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			esub = ss + OPND(m->g->strip[ss]) - 1;
5054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(OP(m->g->strip[esub]) == OOR1);
5064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			for (;;) {	/* find first matching branch */
5074fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				if (slow(m, sp, rest, ssub, esub) == rest)
5084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					break;	/* it matched all of it */
5094fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* that one missed, try next one */
5104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(OP(m->g->strip[esub]) == OOR1);
5114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				esub++;
5124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(OP(m->g->strip[esub]) == OOR2);
5134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				ssub = esub + 1;
5144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				esub += OPND(m->g->strip[esub]);
5154fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				if (OP(m->g->strip[esub]) == OOR2)
5164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					esub--;
5174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				else
5184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					assert(OP(m->g->strip[esub]) == O_CH);
5194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
520cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#ifdef NDEBUG
521cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			(void)
522cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#else
523cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			dp =
524cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes#endif
525cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			    dissect(m, sp, rest, ssub, esub);
5264fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(dp == rest);
5274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			sp = rest;
5284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
5294fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case O_PLUS:
5304fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case O_QUEST:
5314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OOR1:
5324fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OOR2:
5334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case O_CH:
5344fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(nope);
5354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
5364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OLPAREN:
5374fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			i = OPND(m->g->strip[ss]);
5384fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(0 < i && i <= m->g->nsub);
5394fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			m->pmatch[i].rm_so = sp - m->offp;
5404fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
5414fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case ORPAREN:
5424fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			i = OPND(m->g->strip[ss]);
5434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(0 < i && i <= m->g->nsub);
5444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			m->pmatch[i].rm_eo = sp - m->offp;
5454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
5464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		default:		/* uh oh */
5474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(nope);
5484fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
5494fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
5504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
5514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
5524fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	assert(sp == stop);
5534fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	return(sp);
5544fa7b105644222d9b35347c9d226ca8e011072ebColin Cross}
5554fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
5564fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
5574fa7b105644222d9b35347c9d226ca8e011072ebColin Cross - backref - figure out what matched what, figuring in back references
558cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == static const char *backref(struct match *m, const char *start, \
559cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes ==	const char *stop, sopno startst, sopno stopst, sopno lev);
5604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
561cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic const char *		/* == stop (success) or NULL (failure) */
562cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesbackref(
563cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    struct match *m,
564cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    const char *start,
565cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    const char *stop,
566cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno startst,
567cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno stopst,
568cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno lev)			/* PLUS nesting level */
5694fa7b105644222d9b35347c9d226ca8e011072ebColin Cross{
5704fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int i;
5714fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sopno ss;	/* start sop of current subRE */
572cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *sp;	/* start of string matched by it */
5734fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sopno ssub;	/* start sop of subsubRE */
5744fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sopno esub;	/* end sop of subsubRE */
575cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *ssp; /* start of string matched by subsubRE */
576cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *dp;
5774fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	size_t len;
5784fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int hard;
5794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sop s;
5804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	regoff_t offsave;
5814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	cset *cs;
5824fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
583cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(m != NULL);
584cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(start != NULL);
585cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(stop != NULL);
586cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
5874fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	AT("back", start, stop, startst, stopst);
5884fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sp = start;
5894fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
5904fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	/* get as far as we can with easy stuff */
5914fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	hard = 0;
5924fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	for (ss = startst; !hard && ss < stopst; ss++)
5934fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		switch (OP(s = m->g->strip[ss])) {
5944fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OCHAR:
5954fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (sp == stop || *sp++ != (char)OPND(s))
5964fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				return(NULL);
5974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
5984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OANY:
5994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (sp == stop)
6004fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				return(NULL);
6014fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			sp++;
6024fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
6034fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OANYOF:
6044fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			cs = &m->g->sets[OPND(s)];
6054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (sp == stop || !CHIN(cs, *sp++))
6064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				return(NULL);
6074fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
6084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OBOL:
6094fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if ( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
6104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(sp < m->endp && *(sp-1) == '\n' &&
6114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross						(m->g->cflags&REG_NEWLINE)) )
6124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				{ /* yes */ }
6134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			else
6144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				return(NULL);
6154fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
6164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OEOL:
6174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if ( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
6184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(sp < m->endp && *sp == '\n' &&
6194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross						(m->g->cflags&REG_NEWLINE)) )
6204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				{ /* yes */ }
6214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			else
6224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				return(NULL);
6234fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
6244fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OBOW:
6254fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
6264fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(sp < m->endp && *(sp-1) == '\n' &&
6274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross						(m->g->cflags&REG_NEWLINE)) ||
6284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(sp > m->beginp &&
6294fa7b105644222d9b35347c9d226ca8e011072ebColin Cross							!ISWORD(*(sp-1))) ) &&
6304fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(sp < m->endp && ISWORD(*sp)) )
6314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				{ /* yes */ }
6324fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			else
6334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				return(NULL);
6344fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
6354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OEOW:
6364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
6374fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(sp < m->endp && *sp == '\n' &&
6384fa7b105644222d9b35347c9d226ca8e011072ebColin Cross						(m->g->cflags&REG_NEWLINE)) ||
6394fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(sp < m->endp && !ISWORD(*sp)) ) &&
6404fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(sp > m->beginp && ISWORD(*(sp-1))) )
6414fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				{ /* yes */ }
6424fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			else
6434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				return(NULL);
6444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
6454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case O_QUEST:
6464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
6474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OOR1:	/* matches null but needs to skip */
6484fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			ss++;
6494fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			s = m->g->strip[ss];
6504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			do {
6514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(OP(s) == OOR2);
6524fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				ss += OPND(s);
6534fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			} while (OP(s = m->g->strip[ss]) != O_CH);
6544fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			/* note that the ss++ gets us past the O_CH */
6554fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
6564fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		default:	/* have to make a choice */
6574fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			hard = 1;
6584fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
6594fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
6604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (!hard) {		/* that was it! */
6614fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (sp != stop)
6624fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			return(NULL);
6634fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		return(sp);
6644fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
6654fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	ss--;			/* adjust for the for's final increment */
6664fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
6674fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	/* the hard stuff */
6684fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	AT("hard", sp, stop, ss, stopst);
6694fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	s = m->g->strip[ss];
6704fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	switch (OP(s)) {
6714fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	case OBACK_:		/* the vilest depths */
6724fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		i = OPND(s);
6734fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(0 < i && i <= m->g->nsub);
674cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		if (m->pmatch[i].rm_eo == (regoff_t)-1)
6754fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			return(NULL);
676cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		assert(m->pmatch[i].rm_so != (regoff_t)-1);
677cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		len = (size_t)(m->pmatch[i].rm_eo - m->pmatch[i].rm_so);
678cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		if (len == 0)
6794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			return(NULL);
6804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(stop - m->beginp >= len);
6814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (sp > stop - len)
6824fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			return(NULL);	/* not enough left to match */
683cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		ssp = m->offp + (size_t)m->pmatch[i].rm_so;
6844fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (memcmp(sp, ssp, len) != 0)
6854fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			return(NULL);
6864fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		while (m->g->strip[ss] != SOP(O_BACK, i))
6874fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			ss++;
688cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		return(backref(m, sp+len, stop, ss+1, stopst, lev));
689cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
6904fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	case OQUEST_:		/* to null or not */
691cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		dp = backref(m, sp, stop, ss+1, stopst, lev);
6924fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (dp != NULL)
6934fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			return(dp);	/* not */
694cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));
695cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
6964fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	case OPLUS_:
6974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(m->lastpos != NULL);
6984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(lev+1 <= m->g->nplus);
6994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		m->lastpos[lev+1] = sp;
700cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		return(backref(m, sp, stop, ss+1, stopst, lev+1));
701cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
7024fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	case O_PLUS:
7034fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (sp == m->lastpos[lev])	/* last pass matched null */
704cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			return(backref(m, sp, stop, ss+1, stopst, lev-1));
7054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* try another pass */
7064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		m->lastpos[lev] = sp;
707cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);
7084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (dp == NULL)
709cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			dp = backref(m, sp, stop, ss+1, stopst, lev-1);
710cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		return(dp);
711cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
7124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	case OCH_:		/* find the right one, if any */
7134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		ssub = ss + 1;
7144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		esub = ss + OPND(s) - 1;
7154fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(OP(m->g->strip[esub]) == OOR1);
7164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		for (;;) {	/* find first matching branch */
717cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			dp = backref(m, sp, stop, ssub, esub, lev);
7184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (dp != NULL)
7194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				return(dp);
7204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			/* that one missed, try next one */
7214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (OP(m->g->strip[esub]) == O_CH)
7224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				return(NULL);	/* there is none */
7234fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			esub++;
7244fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(OP(m->g->strip[esub]) == OOR2);
7254fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			ssub = esub + 1;
7264fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			esub += OPND(m->g->strip[esub]);
7274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (OP(m->g->strip[esub]) == OOR2)
7284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				esub--;
7294fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			else
7304fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(OP(m->g->strip[esub]) == O_CH);
7314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
732cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
7334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	case OLPAREN:		/* must undo assignment if rest fails */
7344fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		i = OPND(s);
7354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(0 < i && i <= m->g->nsub);
7364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		offsave = m->pmatch[i].rm_so;
7374fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		m->pmatch[i].rm_so = sp - m->offp;
738cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		dp = backref(m, sp, stop, ss+1, stopst, lev);
7394fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (dp != NULL)
7404fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			return(dp);
7414fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		m->pmatch[i].rm_so = offsave;
7424fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		return(NULL);
743cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
7444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	case ORPAREN:		/* must undo assignment if rest fails */
7454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		i = OPND(s);
7464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(0 < i && i <= m->g->nsub);
7474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		offsave = m->pmatch[i].rm_eo;
7484fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		m->pmatch[i].rm_eo = sp - m->offp;
749cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		dp = backref(m, sp, stop, ss+1, stopst, lev);
7504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (dp != NULL)
7514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			return(dp);
7524fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		m->pmatch[i].rm_eo = offsave;
7534fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		return(NULL);
754cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
7554fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	default:		/* uh oh */
7564fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(nope);
7574fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		break;
7584fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
7594fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
7604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	/* "can't happen" */
7614fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	assert(nope);
7624fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	/* NOTREACHED */
763cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	return NULL;
7644fa7b105644222d9b35347c9d226ca8e011072ebColin Cross}
7654fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
7664fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
7674fa7b105644222d9b35347c9d226ca8e011072ebColin Cross - fast - step through the string at top speed
768cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == static const char *fast(struct match *m, const char *start, \
769cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes ==	const char *stop, sopno startst, sopno stopst);
7704fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
771cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic const char *		/* where tentative match ended, or NULL */
772cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesfast(
773cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    struct match *m,
774cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    const char *start,
775cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    const char *stop,
776cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno startst,
777cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno stopst)
7784fa7b105644222d9b35347c9d226ca8e011072ebColin Cross{
7794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states st = m->st;
7804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states fresh = m->fresh;
7814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states tmp = m->tmp;
782cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *p = start;
7834fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int c = (start == m->beginp) ? OUT : *(start-1);
7844fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int lastc;	/* previous c */
7854fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int flagch;
786cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	size_t i;
787cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *coldp; /* last p after which no match was underway */
788cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
789cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(m != NULL);
790cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(start != NULL);
791cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(stop != NULL);
7924fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
7934fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	CLEAR(st);
7944fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	SET1(st, startst);
7954fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	st = step(m->g, startst, stopst, st, NOTHING, st);
7964fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	ASSIGN(fresh, st);
7974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	SP("start", st, *p);
7984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	coldp = NULL;
7994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	for (;;) {
8004fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* next character */
8014fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		lastc = c;
8024fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		c = (p == m->endp) ? OUT : *p;
8034fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (EQ(st, fresh))
8044fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			coldp = p;
8054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
8064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* is there an EOL and/or BOL between lastc and c? */
8074fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		flagch = '\0';
8084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		i = 0;
8094fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
8104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				(lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
8114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			flagch = BOL;
8124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			i = m->g->nbol;
8134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
8144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
8154fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				(c == OUT && !(m->eflags&REG_NOTEOL)) ) {
8164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			flagch = (flagch == BOL) ? BOLEOL : EOL;
8174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			i += m->g->neol;
8184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
8194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (i != 0) {
8204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			for (; i > 0; i--)
8214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				st = step(m->g, startst, stopst, st, flagch, st);
8224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			SP("boleol", st, c);
8234fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
8244fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
8254fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* how about a word boundary? */
8264fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
8274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(c != OUT && ISWORD(c)) ) {
8284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			flagch = BOW;
8294fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
8304fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if ( (lastc != OUT && ISWORD(lastc)) &&
8314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				(flagch == EOL || (c != OUT && !ISWORD(c))) ) {
8324fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			flagch = EOW;
8334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
8344fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (flagch == BOW || flagch == EOW) {
8354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			st = step(m->g, startst, stopst, st, flagch, st);
8364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			SP("boweow", st, c);
8374fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
8384fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
8394fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* are we done? */
8404fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (ISSET(st, stopst) || p == stop)
8414fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;		/* NOTE BREAK OUT */
8424fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
8434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* no, we must deal with this character */
8444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		ASSIGN(tmp, st);
8454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		ASSIGN(st, fresh);
8464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(c != OUT);
8474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		st = step(m->g, startst, stopst, tmp, c, st);
8484fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		SP("aft", st, c);
8494fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
8504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		p++;
8514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
8524fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
8534fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	assert(coldp != NULL);
8544fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	m->coldp = coldp;
8554fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (ISSET(st, stopst))
8564fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		return(p+1);
8574fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	else
8584fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		return(NULL);
8594fa7b105644222d9b35347c9d226ca8e011072ebColin Cross}
8604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
8614fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
8624fa7b105644222d9b35347c9d226ca8e011072ebColin Cross - slow - step through the string more deliberately
863cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == static const char *slow(struct match *m, const char *start, \
864cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes ==	const char *stop, sopno startst, sopno stopst);
8654fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
866cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstatic const char *			/* where it ended */
867cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesslow(
868cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    struct match *m,
869cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    const char *start,
870cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    const char *stop,
871cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno startst,
872cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno stopst)
8734fa7b105644222d9b35347c9d226ca8e011072ebColin Cross{
8744fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states st = m->st;
8754fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states empty = m->empty;
8764fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	states tmp = m->tmp;
877cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *p = start;
8784fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int c = (start == m->beginp) ? OUT : *(start-1);
8794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int lastc;	/* previous c */
8804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int flagch;
881cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	size_t i;
882cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	const char *matchp;	/* last p at which a match ended */
883cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
884cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(m != NULL);
885cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(start != NULL);
886cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(stop != NULL);
8874fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
8884fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	AT("slow", start, stop, startst, stopst);
8894fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	CLEAR(st);
8904fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	SET1(st, startst);
8914fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	SP("sstart", st, *p);
8924fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	st = step(m->g, startst, stopst, st, NOTHING, st);
8934fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	matchp = NULL;
8944fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	for (;;) {
8954fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* next character */
8964fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		lastc = c;
8974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		c = (p == m->endp) ? OUT : *p;
8984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
8994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* is there an EOL and/or BOL between lastc and c? */
9004fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		flagch = '\0';
9014fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		i = 0;
9024fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
9034fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				(lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
9044fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			flagch = BOL;
9054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			i = m->g->nbol;
9064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
9074fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
9084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				(c == OUT && !(m->eflags&REG_NOTEOL)) ) {
9094fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			flagch = (flagch == BOL) ? BOLEOL : EOL;
9104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			i += m->g->neol;
9114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
9124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (i != 0) {
9134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			for (; i > 0; i--)
9144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				st = step(m->g, startst, stopst, st, flagch, st);
9154fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			SP("sboleol", st, c);
9164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
9174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
9184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* how about a word boundary? */
9194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
9204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					(c != OUT && ISWORD(c)) ) {
9214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			flagch = BOW;
9224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
9234fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if ( (lastc != OUT && ISWORD(lastc)) &&
9244fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				(flagch == EOL || (c != OUT && !ISWORD(c))) ) {
9254fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			flagch = EOW;
9264fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
9274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (flagch == BOW || flagch == EOW) {
9284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			st = step(m->g, startst, stopst, st, flagch, st);
9294fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			SP("sboweow", st, c);
9304fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
9314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
9324fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* are we done? */
9334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (ISSET(st, stopst))
9344fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			matchp = p;
9354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (EQ(st, empty) || p == stop)
9364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;		/* NOTE BREAK OUT */
9374fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
9384fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		/* no, we must deal with this character */
9394fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		ASSIGN(tmp, st);
9404fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		ASSIGN(st, empty);
9414fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(c != OUT);
9424fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		st = step(m->g, startst, stopst, tmp, c, st);
9434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		SP("saft", st, c);
9444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
9454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		p++;
9464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
9474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
9484fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	return(matchp);
9494fa7b105644222d9b35347c9d226ca8e011072ebColin Cross}
9504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
9514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
9524fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
9534fa7b105644222d9b35347c9d226ca8e011072ebColin Cross - step - map set of states reachable before char to set reachable after
954cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == static states step(struct re_guts *g, sopno start, sopno stop, \
955cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes ==	states bef, int ch, states aft);
956cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #define	BOL	(OUT+1)
957cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #define	EOL	(BOL+1)
958cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #define	BOLEOL	(BOL+2)
959cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #define	NOTHING	(BOL+3)
960cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #define	BOW	(BOL+4)
961cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #define	EOW	(BOL+5)
962cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #define	CODEMAX	(BOL+5)		// highest code used
963cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #define	NONCHAR(c)	((c) > CHAR_MAX)
964cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #define	NNONCHAR	(CODEMAX-CHAR_MAX)
9654fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
9664fa7b105644222d9b35347c9d226ca8e011072ebColin Crossstatic states
967cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesstep(
968cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    struct re_guts *g,
9694fa7b105644222d9b35347c9d226ca8e011072ebColin Cross    sopno start,		/* start state within strip */
9704fa7b105644222d9b35347c9d226ca8e011072ebColin Cross    sopno stop,			/* state after stop state within strip */
9714fa7b105644222d9b35347c9d226ca8e011072ebColin Cross    states bef,			/* states reachable before */
9724fa7b105644222d9b35347c9d226ca8e011072ebColin Cross    int ch,			/* character or NONCHAR code */
9734fa7b105644222d9b35347c9d226ca8e011072ebColin Cross    states aft)			/* states already known reachable after */
9744fa7b105644222d9b35347c9d226ca8e011072ebColin Cross{
9754fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	cset *cs;
9764fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sop s;
9774fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sopno pc;
9784fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	onestate here;		/* note, macros know this name */
9794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	sopno look;
9804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int i;
9814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
982cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(g != NULL);
983cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
9844fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {
9854fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		s = g->strip[pc];
9864fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		switch (OP(s)) {
9874fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OEND:
9884fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(pc == stop-1);
9894fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
9904fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OCHAR:
9914fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			/* only characters can match */
9924fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(!NONCHAR(ch) || ch != (char)OPND(s));
9934fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (ch == (char)OPND(s))
9944fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				FWD(aft, bef, 1);
9954fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
9964fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OBOL:
9974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (ch == BOL || ch == BOLEOL)
9984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				FWD(aft, bef, 1);
9994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10004fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OEOL:
10014fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (ch == EOL || ch == BOLEOL)
10024fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				FWD(aft, bef, 1);
10034fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10044fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OBOW:
10054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (ch == BOW)
10064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				FWD(aft, bef, 1);
10074fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10084fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OEOW:
10094fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (ch == EOW)
10104fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				FWD(aft, bef, 1);
10114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10124fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OANY:
10134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (!NONCHAR(ch))
10144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				FWD(aft, bef, 1);
10154fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OANYOF:
10174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			cs = &g->sets[OPND(s)];
10184fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (!NONCHAR(ch) && CHIN(cs, ch))
10194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				FWD(aft, bef, 1);
10204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OBACK_:		/* ignored here */
10224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case O_BACK:
10234fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, 1);
10244fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10254fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OPLUS_:		/* forward, this is just an empty */
10264fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, 1);
10274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10284fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case O_PLUS:		/* both forward and back */
10294fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, 1);
10304fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			i = ISSETBACK(aft, OPND(s));
10314fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			BACK(aft, aft, OPND(s));
10324fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (!i && ISSETBACK(aft, OPND(s))) {
10334fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				/* oho, must reconsider loop body */
10344fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				pc -= OPND(s) + 1;
10354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				INIT(here, pc);
10364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
10374fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10384fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OQUEST_:		/* two branches, both forward */
10394fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, 1);
10404fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, OPND(s));
10414fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10424fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case O_QUEST:		/* just an empty */
10434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, 1);
10444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OLPAREN:		/* not significant here */
10464fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case ORPAREN:
10474fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, 1);
10484fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10494fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OCH_:		/* mark the first two branches */
10504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, 1);
10514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(OP(g->strip[pc+OPND(s)]) == OOR2);
10524fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, OPND(s));
10534fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10544fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OOR1:		/* done a branch, find the O_CH */
10554fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (ISSTATEIN(aft, here)) {
10564fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				for (look = 1;
10574fa7b105644222d9b35347c9d226ca8e011072ebColin Cross						OP(s = g->strip[pc+look]) != O_CH;
10584fa7b105644222d9b35347c9d226ca8e011072ebColin Cross						look += OPND(s))
10594fa7b105644222d9b35347c9d226ca8e011072ebColin Cross					assert(OP(s) == OOR2);
10604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				FWD(aft, aft, look);
10614fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
10624fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10634fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case OOR2:		/* propagate OCH_'s marking */
10644fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, 1);
10654fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			if (OP(g->strip[pc+OPND(s)]) != O_CH) {
10664fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				assert(OP(g->strip[pc+OPND(s)]) == OOR2);
10674fa7b105644222d9b35347c9d226ca8e011072ebColin Cross				FWD(aft, aft, OPND(s));
10684fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			}
10694fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10704fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		case O_CH:		/* just empty */
10714fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			FWD(aft, aft, 1);
10724fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10734fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		default:		/* ooooops... */
10744fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			assert(nope);
10754fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			break;
10764fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
10774fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	}
10784fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
10794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	return(aft);
10804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross}
10814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
10824fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#ifdef REDEBUG
10834fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
10844fa7b105644222d9b35347c9d226ca8e011072ebColin Cross - print - print a set of states
1085cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #ifdef REDEBUG
1086cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == static void print(struct match *m, char *caption, states st, \
1087cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes ==	int ch, FILE *d);
1088cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #endif
10894fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
10904fa7b105644222d9b35347c9d226ca8e011072ebColin Crossstatic void
1091cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesprint(
1092cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    struct match *m,
1093cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    char *caption,
1094cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    states st,
1095cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    int ch,
1096cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    FILE *d)
10974fa7b105644222d9b35347c9d226ca8e011072ebColin Cross{
10984fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	struct re_guts *g = m->g;
10994fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int i;
11004fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	int first = 1;
11014fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
1102cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(m != NULL);
1103cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(caption != NULL);
1104cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
11054fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (!(m->eflags&REG_TRACE))
11064fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		return;
11074fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
1108cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(d != NULL);
1109cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
1110cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	fprintf(d, "%s", caption);
11114fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (ch != '\0')
1112cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes		fprintf(d, " %s", pchar(ch));
11134fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	for (i = 0; i < g->nstates; i++)
11144fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		if (ISSET(st, i)) {
1115cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes			fprintf(d, "%s%d", (first) ? "\t" : ", ", i);
11164fa7b105644222d9b35347c9d226ca8e011072ebColin Cross			first = 0;
11174fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		}
1118cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	fprintf(d, "\n");
11194fa7b105644222d9b35347c9d226ca8e011072ebColin Cross}
11204fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
11214fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
11224fa7b105644222d9b35347c9d226ca8e011072ebColin Cross - at - print current situation
1123cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #ifdef REDEBUG
1124cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == static void at(struct match *m, char *title, char *start, char *stop, \
1125cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes ==						sopno startst, sopno stopst);
1126cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #endif
11274fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
11284fa7b105644222d9b35347c9d226ca8e011072ebColin Crossstatic void
1129cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughesat(
1130cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    struct match *m,
1131cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    char *title,
1132cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    char *start,
1133cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    char *stop,
1134cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    sopno startst,
11354fa7b105644222d9b35347c9d226ca8e011072ebColin Cross    sopno stopst)
11364fa7b105644222d9b35347c9d226ca8e011072ebColin Cross{
1137cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
1138cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(m != NULL);
1139cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(title != NULL);
1140cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(start != NULL);
1141cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	_DIAGASSERT(stop != NULL);
1142cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes
11434fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (!(m->eflags&REG_TRACE))
11444fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		return;
11454fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
1146cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	printf("%s %s-", title, pchar(*start));
1147cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	printf("%s ", pchar(*stop));
1148cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes	printf("%ld-%ld\n", (long)startst, (long)stopst);
11494fa7b105644222d9b35347c9d226ca8e011072ebColin Cross}
11504fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
11514fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#ifndef PCHARDONE
11524fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#define	PCHARDONE	/* never again */
11534fa7b105644222d9b35347c9d226ca8e011072ebColin Cross/*
11544fa7b105644222d9b35347c9d226ca8e011072ebColin Cross - pchar - make a character printable
1155cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #ifdef REDEBUG
1156cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == static char *pchar(int ch);
1157cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes == #endif
11584fa7b105644222d9b35347c9d226ca8e011072ebColin Cross *
11594fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * Is this identical to regchar() over in debug.c?  Well, yes.  But a
11604fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * duplicate here avoids having a debugging-capable regexec.o tied to
11614fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * a matching debug.o, and this is convenient.  It all disappears in
11624fa7b105644222d9b35347c9d226ca8e011072ebColin Cross * the non-debug compilation anyway, so it doesn't matter much.
11634fa7b105644222d9b35347c9d226ca8e011072ebColin Cross */
11644fa7b105644222d9b35347c9d226ca8e011072ebColin Crossstatic char *			/* -> representation */
1165cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughespchar(
1166cc213f871bf4c5329eb5eb7a80a0ce9d4a880af8Elliott Hughes    int ch)
11674fa7b105644222d9b35347c9d226ca8e011072ebColin Cross{
11684fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	static char pbuf[10];
11694fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
11704fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	if (isprint(ch) || ch == ' ')
11714fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		(void)snprintf(pbuf, sizeof pbuf, "%c", ch);
11724fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	else
11734fa7b105644222d9b35347c9d226ca8e011072ebColin Cross		(void)snprintf(pbuf, sizeof pbuf, "\\%o", ch);
11744fa7b105644222d9b35347c9d226ca8e011072ebColin Cross	return(pbuf);
11754fa7b105644222d9b35347c9d226ca8e011072ebColin Cross}
11764fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#endif
11774fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#endif
11784fa7b105644222d9b35347c9d226ca8e011072ebColin Cross
11794fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	matcher
11804fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	fast
11814fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	slow
11824fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	dissect
11834fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	backref
11844fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	step
11854fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	print
11864fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	at
11874fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	match
11884fa7b105644222d9b35347c9d226ca8e011072ebColin Cross#undef	nope
1189