⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 engine.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1992, 1993, 1994 Henry Spencer. * Copyright (c) 1992, 1993, 1994 *		The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Henry Spencer. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *	  notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *	  notice, this list of conditions and the following disclaimer in the *	  documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *	  must display the following acknowledgement: *		This product includes software developed by the University of *		California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *	  may be used to endorse or promote products derived from this software *	  without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.	IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *		@(#)engine.c	8.5 (Berkeley) 3/20/94 *//* * The matching engine and friends.  This file is #included by regexec.c * after suitable #defines of a variety of macros used herein, so that * different state representations can be used without duplicating masses * of code. */#ifdef SNAMES#define matcher smatcher#define fast	sfast#define slow	sslow#define dissect sdissect#define backref sbackref#define step	sstep#define print	sprint#define at		sat#define match	smat#endif#ifdef LNAMES#define matcher lmatcher#define fast	lfast#define slow	lslow#define dissect ldissect#define backref lbackref#define step	lstep#define print	lprint#define at		lat#define match	lmat#endif/* another structure passed up and down to avoid zillions of parameters */struct match{	struct re_guts *g;	int			eflags;	regmatch_t *pmatch;			/* [nsub+1] (0 element unused) */	pg_wchar   *offp;			/* offsets work from here */	pg_wchar   *beginp;			/* start of string -- virtual NUL precedes */	pg_wchar   *endp;			/* end of string -- virtual NUL here */	pg_wchar   *coldp;			/* can be no match starting before here */	pg_wchar  **lastpos;		/* [nplus+1] */				STATEVARS;	states		st;				/* current states */	states		fresh;			/* states for a fresh start */	states		tmp;			/* temporary */	states		empty;			/* empty set of states */};/* ========= begin header generated by ./mkh ========= */#ifdef __cplusplusextern		"C"{#endif/* === engine.c === */	static int				matcher(struct re_guts * g, pg_wchar * string, size_t nmatch,									regmatch_t *pmatch, int eflags);	static pg_wchar *				dissect(struct match * m, pg_wchar * start, pg_wchar * stop,									sopno startst, sopno stopst);	static pg_wchar *				backref(struct match * m, pg_wchar * start, pg_wchar * stop,								 sopno startst, sopno stopst, sopno lev);	static pg_wchar *				fast(struct match * m, pg_wchar * start, pg_wchar * stop,								 sopno startst, sopno stopst);	static pg_wchar *				slow(struct match * m, pg_wchar * start, pg_wchar * stop, sopno startst, sopno stopst);	static		states				step(struct re_guts * g, sopno start,							 sopno stop, states bef, int ch, states aft);#define BOL		(OUT+1)#define EOL		(BOL+1)#define BOLEOL	(BOL+2)#define NOTHING (BOL+3)#define BOW		(BOL+4)#define EOW		(BOL+5)#define CODEMAX (BOL+5)			/* highest code used */#ifdef MULTIBYTE#define NONCHAR(c)	  ((c) > 16777216)	/* 16777216 == 2^24 == 3 bytes */#define NNONCHAR  (CODEMAX-16777216)#else#define NONCHAR(c)		  ((c) > CHAR_MAX)#define NNONCHAR	  (CODEMAX-CHAR_MAX)#endif#ifdef REDEBUG	static void				print(struct match * m, pg_wchar * caption, states st, int ch, FILE *d);#endif#ifdef REDEBUG	static void				at(struct match * m, pg_wchar * title, pg_wchar * start, pg_wchar * stop,							   sopno startst, sopno stopst);#endif#ifdef REDEBUG	static pg_wchar *				p_char(int ch);#endif#ifdef __cplusplus}#endif/* ========= end header generated by ./mkh ========= */#ifdef REDEBUG#define SP(t, s, c)		print(m, t, s, c, stdout)#define AT(t, p1, p2, s1, s2)	at(m, t, p1, p2, s1, s2)#define NOTE(str)		{ if (m->eflags&REG_TRACE) printf("=%s\n", (str)); }#else#define SP(t, s, c)				/* nothing */#define AT(t, p1, p2, s1, s2)	/* nothing */#define NOTE(s)					/* nothing */#endif/* - matcher - the actual matching engine == static int matcher(struct re_guts *g, pg_wchar *string, \ ==		size_t nmatch, regmatch_t *pmatch, int eflags); */static int						/* 0 success, REG_NOMATCH failure */matcher(g, string, nmatch, pmatch, eflags)struct re_guts *g;pg_wchar   *string;size_t		nmatch;regmatch_t *pmatch;int			eflags;{	pg_wchar   *endp;	int			i;	struct match mv;	struct match *m = &mv;	pg_wchar   *dp;	const sopno gf = g->firststate + 1; /* +1 for OEND */	const sopno gl = g->laststate;	pg_wchar   *start;	pg_wchar   *stop;	/* simplify the situation where possible */	if (g->cflags & REG_NOSUB)		nmatch = 0;	if (eflags & REG_STARTEND)	{		start = string + pmatch[0].rm_so;		stop = string + pmatch[0].rm_eo;	}	else	{		start = string;#ifdef MULTIBYTE		stop = start + pg_wchar_strlen(start);#else		stop = start + strlen(start);#endif	}	if (stop < start)		return REG_INVARG;	/* prescreening; this does wonders for this rather slow code */	if (g->must != NULL)	{		for (dp = start; dp < stop; dp++)			if (*dp == g->must[0] && stop - dp >= g->mlen &&#ifdef MULTIBYTE				memcmp(dp, g->must, (size_t) (g->mlen * sizeof(pg_wchar))) == 0)#else				memcmp(dp, g->must, (size_t) g->mlen) == 0)#endif				break;		if (dp == stop)			/* we didn't find g->must */			return REG_NOMATCH;	}	/* match struct setup */	m->g = g;	m->eflags = eflags;	m->pmatch = NULL;	m->lastpos = NULL;	m->offp = string;	m->beginp = start;	m->endp = stop;	STATESETUP(m, 4);	SETUP(m->st);	SETUP(m->fresh);	SETUP(m->tmp);	SETUP(m->empty);	CLEAR(m->empty);	/* this loop does only one repetition except for backrefs */	for (;;)	{		endp = fast(m, start, stop, gf, gl);		if (endp == NULL)		{						/* a miss */			STATETEARDOWN(m);			return REG_NOMATCH;		}		if (nmatch == 0 && !g->backrefs)			break;				/* no further info needed */		/* where? */		assert(m->coldp != NULL);		for (;;)		{			NOTE("finding start");			endp = slow(m, m->coldp, stop, gf, gl);			if (endp != NULL)				break;			assert(m->coldp < m->endp);			m->coldp++;		}		if (nmatch == 1 && !g->backrefs)			break;				/* no further info needed */		/* oh my, he wants the subexpressions... */		if (m->pmatch == NULL)			m->pmatch = (regmatch_t *) malloc((m->g->nsub + 1) *											  sizeof(regmatch_t));		if (m->pmatch == NULL)		{			STATETEARDOWN(m);			return REG_ESPACE;		}		for (i = 1; i <= m->g->nsub; i++)			m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;		if (!g->backrefs && !(m->eflags & REG_BACKR))		{			NOTE("dissecting");			dp = dissect(m, m->coldp, endp, gf, gl);		}		else		{			if (g->nplus > 0 && m->lastpos == NULL)				m->lastpos = (pg_wchar **) malloc((g->nplus + 1) *												  sizeof(pg_wchar *));			if (g->nplus > 0 && m->lastpos == NULL)			{				free(m->pmatch);				STATETEARDOWN(m);				return REG_ESPACE;			}			NOTE("backref dissect");			dp = backref(m, m->coldp, endp, gf, gl, (sopno) 0);		}		if (dp != NULL)			break;		/* uh-oh... we couldn't find a subexpression-level match */		assert(g->backrefs);	/* must be back references doing it */		assert(g->nplus == 0 || m->lastpos != NULL);		for (;;)		{			if (dp != NULL || endp <= m->coldp)				break;			/* defeat */			NOTE("backoff");			endp = slow(m, m->coldp, endp - 1, gf, gl);			if (endp == NULL)				break;			/* defeat */			/* try it on a shorter possibility */#ifndef NDEBUG			for (i = 1; i <= m->g->nsub; i++)			{				assert(m->pmatch[i].rm_so == -1);				assert(m->pmatch[i].rm_eo == -1);			}#endif			NOTE("backoff dissect");			dp = backref(m, m->coldp, endp, gf, gl, (sopno) 0);		}		assert(dp == NULL || dp == endp);		if (dp != NULL)			/* found a shorter one */			break;		/* despite initial appearances, there is no match here */		NOTE("false alarm");		start = m->coldp + 1;	/* recycle starting later */		assert(start <= stop);	}	/* fill in the details if requested */	if (nmatch > 0)	{		pmatch[0].rm_so = m->coldp - m->offp;		pmatch[0].rm_eo = endp - m->offp;	}	if (nmatch > 1)	{		assert(m->pmatch != NULL);		for (i = 1; i < nmatch; i++)			if (i <= m->g->nsub)				pmatch[i] = m->pmatch[i];			else			{				pmatch[i].rm_so = -1;				pmatch[i].rm_eo = -1;			}	}	if (m->pmatch != NULL)		free((pg_wchar *) m->pmatch);	if (m->lastpos != NULL)		free((pg_wchar *) m->lastpos);	STATETEARDOWN(m);	return 0;}/* - dissect - figure out what matched what, no back references == static char *dissect(struct match *m, char *start, \ ==		char *stop, sopno startst, sopno stopst); */static pg_wchar *				/* == stop (success) always */dissect(m, start, stop, startst, stopst)struct match *m;pg_wchar   *start;pg_wchar   *stop;sopno		startst;sopno		stopst;{	int			i;	sopno		ss;				/* start sop of current subRE */	sopno		es;				/* end sop of current subRE */	pg_wchar   *sp;				/* start of string matched by it */	pg_wchar   *stp;			/* string matched by it cannot pass here */	pg_wchar   *rest;			/* start of rest of string */	pg_wchar   *tail;			/* string unmatched by rest of RE */	sopno		ssub;			/* start sop of subsubRE */	sopno		esub;			/* end sop of subsubRE */	pg_wchar   *ssp;			/* start of string matched by subsubRE */	pg_wchar   *sep;			/* end of string matched by subsubRE */	pg_wchar   *oldssp;			/* previous ssp */	pg_wchar   *dp;	AT("diss", start, stop, startst, stopst);	sp = start;	for (ss = startst; ss < stopst; ss = es)	{		/* identify end of subRE */		es = ss;		switch (OP(m->g->strip[es]))		{			case OPLUS_:			case OQUEST_:				es += OPND(m->g->strip[es]);				break;			case OCH_:				while (OP(m->g->strip[es]) != O_CH)					es += OPND(m->g->strip[es]);				break;		}		es++;		/* figure out what it matched */		switch (OP(m->g->strip[ss]))		{			case OEND:				assert(nope);				break;			case OCHAR:				sp++;				break;			case OBOL:			case OEOL:			case OBOW:			case OEOW:				break;			case OANY:			case OANYOF:				sp++;				break;			case OBACK_:			case O_BACK:				assert(nope);				break;				/* cases where length of match is hard to find */			case OQUEST_:				stp = stop;				for (;;)				{					/* how long could this one be? */					rest = slow(m, sp, stp, ss, es);					assert(rest != NULL);		/* it did match */					/* could the rest match the rest? */					tail = slow(m, rest, stop, es, stopst);					if (tail == stop)						break;	/* yes! */					/* no -- try a shorter match for this one */					stp = rest - 1;					assert(stp >= sp);	/* it did work */				}				ssub = ss + 1;				esub = es - 1;				/* did innards match? */				if (slow(m, sp, rest, ssub, esub) != NULL)				{					dp = dissect(m, sp, rest, ssub, esub);					assert(dp == rest);				}				else/* no */					assert(sp == rest);				sp = rest;				break;			case OPLUS_:				stp = stop;				for (;;)				{					/* how long could this one be? */					rest = slow(m, sp, stp, ss, es);					assert(rest != NULL);		/* it did match */					/* could the rest match the rest? */					tail = slow(m, rest, stop, es, stopst);					if (tail == stop)						break;	/* yes! */					/* no -- try a shorter match for this one */					stp = rest - 1;					assert(stp >= sp);	/* it did work */				}				ssub = ss + 1;				esub = es - 1;				ssp = sp;				oldssp = ssp;				for (;;)				{				/* find last match of innards */					sep = slow(m, ssp, rest, ssub, esub);					if (sep == NULL || sep == ssp)						break;	/* failed or matched null */					oldssp = ssp;		/* on to next try */					ssp = sep;				}				if (sep == NULL)				{					/* last successful match */					sep = ssp;					ssp = oldssp;				}				assert(sep == rest);	/* must exhaust substring */				assert(slow(m, ssp, sep, ssub, esub) == rest);				dp = dissect(m, ssp, sep, ssub, esub);				assert(dp == sep);				sp = rest;				break;			case OCH_:				stp = stop;				for (;;)				{					/* how long could this one be? */					rest = slow(m, sp, stp, ss, es);					assert(rest != NULL);		/* it did match */					/* could the rest match the rest? */					tail = slow(m, rest, stop, es, stopst);					if (tail == stop)						break;	/* yes! */					/* no -- try a shorter match for this one */					stp = rest - 1;					assert(stp >= sp);	/* it did work */				}				ssub = ss + 1;				esub = ss + OPND(m->g->strip[ss]) - 1;				assert(OP(m->g->strip[esub]) == OOR1);				for (;;)				{				/* find first matching branch */					if (slow(m, sp, rest, ssub, esub) == rest)						break;	/* it matched all of it */					/* that one missed, try next one */					assert(OP(m->g->strip[esub]) == OOR1);					esub++;					assert(OP(m->g->strip[esub]) == OOR2);					ssub = esub + 1;					esub += OPND(m->g->strip[esub]);					if (OP(m->g->strip[esub]) == OOR2)						esub--;					else						assert(OP(m->g->strip[esub]) == O_CH);				}				dp = dissect(m, sp, rest, ssub, esub);				assert(dp == rest);				sp = rest;				break;			case O_PLUS:			case O_QUEST:			case OOR1:			case OOR2:			case O_CH:				assert(nope);				break;			case OLPAREN:				i = OPND(m->g->strip[ss]);				assert(0 < i && i <= m->g->nsub);				m->pmatch[i].rm_so = sp - m->offp;				break;			case ORPAREN:				i = OPND(m->g->strip[ss]);				assert(0 < i && i <= m->g->nsub);				m->pmatch[i].rm_eo = sp - m->offp;				break;			default:			/* uh oh */				assert(nope);				break;		}	}	assert(sp == stop);	return sp;}/* - backref - figure out what matched what, figuring in back references == static char *backref(struct match *m, char *start, \ ==		char *stop, sopno startst, sopno stopst, sopno lev); */static pg_wchar *				/* == stop (success) or NULL (failure) */backref(m, start, stop, startst, stopst, lev)struct match *m;pg_wchar   *start;pg_wchar   *stop;sopno		startst;sopno		stopst;sopno		lev;				/* PLUS nesting level */{	int			i;	sopno		ss;				/* start sop of current subRE */	pg_wchar   *sp;				/* start of string matched by it */	sopno		ssub;			/* start sop of subsubRE */	sopno		esub;			/* end sop of subsubRE */	pg_wchar   *ssp;			/* start of string matched by subsubRE */	pg_wchar   *dp;	size_t		len;	int			hard;	sop			s;	regoff_t	offsave;	cset	   *cs;	AT("back", start, stop, startst, stopst);	sp = start;	/* get as far as we can with easy stuff */	hard = 0;	for (ss = startst; !hard && ss < stopst; ss++)		switch (OP(s = m->g->strip[ss]))		{			case OCHAR:				if (sp == stop || *sp++ != (pg_wchar) OPND(s))					return NULL;				break;			case OANY:				if (sp == stop)					return NULL;				sp++;				break;			case OANYOF:				cs = &m->g->sets[OPND(s)];				if (sp == stop || !CHIN(cs, *sp++))

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -