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

📄 regc_nfa.c

📁 从一个开源软件中摘取的正则表达式模块
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * NFA utilities. * This file is #included by regcomp.c. * * Copyright (c) 1998, 1999 Henry Spencer.	All rights reserved. * * Development of this software was funded, in part, by Cray Research Inc., * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics * Corporation, none of whom are responsible for the results.  The author * thanks all of them. * * Redistribution and use in source and binary forms -- with or without * modification -- are permitted for any purpose, provided that * redistributions in source form retain this entire copyright notice and * indicate the origin and nature of any modifications. * * I'd appreciate being given credit for this package in the documentation * of software which uses it, but that is not a requirement. * * THIS SOFTWARE IS PROVIDED ``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 * HENRY SPENCER 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. * * $PostgreSQL: pgsql/src/backend/regex/regc_nfa.c,v 1.5 2008/01/03 20:47:55 tgl Exp $ * * * One or two things that technically ought to be in here * are actually in color.c, thanks to some incestuous relationships in * the color chains. */#define NISERR()	VISERR(nfa->v)#define NERR(e)		VERR(nfa->v, (e))/* * newnfa - set up an NFA */static struct nfa *				/* the NFA, or NULL */newnfa(struct vars * v, struct colormap * cm, struct nfa * parent)		/* NULL if primary NFA */{	struct nfa *nfa;	nfa = (struct nfa *) MALLOC(sizeof(struct nfa));	if (nfa == NULL)		return NULL;	nfa->states = NULL;	nfa->slast = NULL;	nfa->free = NULL;	nfa->nstates = 0;	nfa->cm = cm;	nfa->v = v;	nfa->size = 0;	nfa->bos[0] = nfa->bos[1] = COLORLESS;	nfa->eos[0] = nfa->eos[1] = COLORLESS;	nfa->parent = parent;		/* Precedes newfstate so parent is valid. */	nfa->post = newfstate(nfa, '@');	/* number 0 */	nfa->pre = newfstate(nfa, '>');		/* number 1 */	nfa->init = newstate(nfa);	/* may become invalid later */	nfa->final = newstate(nfa);	if (ISERR())	{		freenfa(nfa);		return NULL;	}	rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->pre, nfa->init);	newarc(nfa, '^', 1, nfa->pre, nfa->init);	newarc(nfa, '^', 0, nfa->pre, nfa->init);	rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->final, nfa->post);	newarc(nfa, '$', 1, nfa->final, nfa->post);	newarc(nfa, '$', 0, nfa->final, nfa->post);	if (ISERR())	{		freenfa(nfa);		return NULL;	}	return nfa;}/* * TooManyStates - checks if the max states exceeds the compile-time value */static intTooManyStates(struct nfa *nfa){	struct nfa *parent = nfa->parent;	size_t		sz = nfa->size;	while (parent != NULL)	{		sz = parent->size;		parent = parent->parent;	}	if (sz > REG_MAX_STATES)		return 1;	return 0;}/* * IncrementSize - increases the tracked size of the NFA and its parents. */static voidIncrementSize(struct nfa *nfa){	struct nfa *parent = nfa->parent;	nfa->size++;	while (parent != NULL)	{		parent->size++;		parent = parent->parent;	}}/* * DecrementSize - decreases the tracked size of the NFA and its parents. */static voidDecrementSize(struct nfa *nfa){	struct nfa *parent = nfa->parent;	nfa->size--;	while (parent != NULL)	{		parent->size--;		parent = parent->parent;	}}/* * freenfa - free an entire NFA */static voidfreenfa(struct nfa * nfa){	struct state *s;	while ((s = nfa->states) != NULL)	{		s->nins = s->nouts = 0; /* don't worry about arcs */		freestate(nfa, s);	}	while ((s = nfa->free) != NULL)	{		nfa->free = s->next;		destroystate(nfa, s);	}	nfa->slast = NULL;	nfa->nstates = -1;	nfa->pre = NULL;	nfa->post = NULL;	FREE(nfa);}/* * newstate - allocate an NFA state, with zero flag value */static struct state *			/* NULL on error */newstate(struct nfa * nfa){	struct state *s;	if (TooManyStates(nfa))	{		NERR(REG_ETOOBIG);		return NULL;	}	if (nfa->free != NULL)	{		s = nfa->free;		nfa->free = s->next;	}	else	{		s = (struct state *) MALLOC(sizeof(struct state));		if (s == NULL)		{			NERR(REG_ESPACE);			return NULL;		}		s->oas.next = NULL;		s->free = NULL;		s->noas = 0;	}	assert(nfa->nstates >= 0);	s->no = nfa->nstates++;	s->flag = 0;	if (nfa->states == NULL)		nfa->states = s;	s->nins = 0;	s->ins = NULL;	s->nouts = 0;	s->outs = NULL;	s->tmp = NULL;	s->next = NULL;	if (nfa->slast != NULL)	{		assert(nfa->slast->next == NULL);		nfa->slast->next = s;	}	s->prev = nfa->slast;	nfa->slast = s;	/* track the current size and the parent size */	IncrementSize(nfa);	return s;}/* * newfstate - allocate an NFA state with a specified flag value */static struct state *			/* NULL on error */newfstate(struct nfa * nfa, int flag){	struct state *s;	s = newstate(nfa);	if (s != NULL)		s->flag = (char) flag;	return s;}/* * dropstate - delete a state's inarcs and outarcs and free it */static voiddropstate(struct nfa * nfa,		  struct state * s){	struct arc *a;	while ((a = s->ins) != NULL)		freearc(nfa, a);	while ((a = s->outs) != NULL)		freearc(nfa, a);	freestate(nfa, s);}/* * freestate - free a state, which has no in-arcs or out-arcs */static voidfreestate(struct nfa * nfa,		  struct state * s){	assert(s != NULL);	assert(s->nins == 0 && s->nouts == 0);	s->no = FREESTATE;	s->flag = 0;	if (s->next != NULL)		s->next->prev = s->prev;	else	{		assert(s == nfa->slast);		nfa->slast = s->prev;	}	if (s->prev != NULL)		s->prev->next = s->next;	else	{		assert(s == nfa->states);		nfa->states = s->next;	}	s->prev = NULL;	s->next = nfa->free;		/* don't delete it, put it on the free list */	nfa->free = s;	DecrementSize(nfa);}/* * destroystate - really get rid of an already-freed state */static voiddestroystate(struct nfa * nfa,			 struct state * s){	struct arcbatch *ab;	struct arcbatch *abnext;	assert(s->no == FREESTATE);	for (ab = s->oas.next; ab != NULL; ab = abnext)	{		abnext = ab->next;		FREE(ab);	}	s->ins = NULL;	s->outs = NULL;	s->next = NULL;	FREE(s);}/* * newarc - set up a new arc within an NFA */static voidnewarc(struct nfa * nfa,	   int t,	   pcolor co,	   struct state * from,	   struct state * to){	struct arc *a;	assert(from != NULL && to != NULL);	/* check for duplicates */	for (a = from->outs; a != NULL; a = a->outchain)		if (a->to == to && a->co == co && a->type == t)			return;	a = allocarc(nfa, from);	if (NISERR())		return;	assert(a != NULL);	a->type = t;	a->co = (color) co;	a->to = to;	a->from = from;	/*	 * Put the new arc on the beginning, not the end, of the chains. Not only	 * is this easier, it has the very useful side effect that deleting the	 * most-recently-added arc is the cheapest case rather than the most	 * expensive one.	 */	a->inchain = to->ins;	to->ins = a;	a->outchain = from->outs;	from->outs = a;	from->nouts++;	to->nins++;	if (COLORED(a) && nfa->parent == NULL)		colorchain(nfa->cm, a);	return;}/* * allocarc - allocate a new out-arc within a state */static struct arc *				/* NULL for failure */allocarc(struct nfa * nfa,		 struct state * s){	struct arc *a;	struct arcbatch *new;	int			i;	/* shortcut */	if (s->free == NULL && s->noas < ABSIZE)	{		a = &s->oas.a[s->noas];		s->noas++;		return a;	}	/* if none at hand, get more */	if (s->free == NULL)	{		new = (struct arcbatch *) MALLOC(sizeof(struct arcbatch));		if (new == NULL)		{			NERR(REG_ESPACE);			return NULL;		}		new->next = s->oas.next;		s->oas.next = new;		for (i = 0; i < ABSIZE; i++)		{			new->a[i].type = 0;			new->a[i].freechain = &new->a[i + 1];		}		new->a[ABSIZE - 1].freechain = NULL;		s->free = &new->a[0];	}	assert(s->free != NULL);	a = s->free;	s->free = a->freechain;	return a;}/* * freearc - free an arc */static voidfreearc(struct nfa * nfa,		struct arc * victim){	struct state *from = victim->from;	struct state *to = victim->to;	struct arc *a;	assert(victim->type != 0);	/* take it off color chain if necessary */	if (COLORED(victim) && nfa->parent == NULL)		uncolorchain(nfa->cm, victim);	/* take it off source's out-chain */	assert(from != NULL);	assert(from->outs != NULL);	a = from->outs;	if (a == victim)			/* simple case:  first in chain */		from->outs = victim->outchain;	else	{		for (; a != NULL && a->outchain != victim; a = a->outchain)			continue;		assert(a != NULL);		a->outchain = victim->outchain;	}	from->nouts--;	/* take it off target's in-chain */	assert(to != NULL);	assert(to->ins != NULL);	a = to->ins;	if (a == victim)			/* simple case:  first in chain */		to->ins = victim->inchain;	else	{		for (; a != NULL && a->inchain != victim; a = a->inchain)			continue;		assert(a != NULL);		a->inchain = victim->inchain;	}	to->nins--;	/* clean up and place on free list */	victim->type = 0;	victim->from = NULL;		/* precautions... */	victim->to = NULL;	victim->inchain = NULL;	victim->outchain = NULL;	victim->freechain = from->free;	from->free = victim;}/* * findarc - find arc, if any, from given source with given type and color * If there is more than one such arc, the result is random. */static struct arc *findarc(struct state * s,		int type,		pcolor co){	struct arc *a;	for (a = s->outs; a != NULL; a = a->outchain)		if (a->type == type && a->co == co)			return a;	return NULL;}/* * cparc - allocate a new arc within an NFA, copying details from old one */static voidcparc(struct nfa * nfa,	  struct arc * oa,	  struct state * from,	  struct state * to){	newarc(nfa, oa->type, oa->co, from, to);}/* * moveins - move all in arcs of a state to another state * * You might think this could be done better by just updating the * existing arcs, and you would be right if it weren't for the desire * for duplicate suppression, which makes it easier to just make new * ones to exploit the suppression built into newarc. */static voidmoveins(struct nfa * nfa,		struct state * old,		struct state * new){	struct arc *a;	assert(old != new);	while ((a = old->ins) != NULL)	{		cparc(nfa, a, a->from, new);		freearc(nfa, a);	}	assert(old->nins == 0);	assert(old->ins == NULL);}/* * copyins - copy all in arcs of a state to another state */static voidcopyins(struct nfa * nfa,		struct state * old,		struct state * new){	struct arc *a;	assert(old != new);	for (a = old->ins; a != NULL; a = a->inchain)		cparc(nfa, a, a->from, new);}/* * moveouts - move all out arcs of a state to another state */static voidmoveouts(struct nfa * nfa,		 struct state * old,		 struct state * new){	struct arc *a;	assert(old != new);	while ((a = old->outs) != NULL)	{		cparc(nfa, a, new, a->to);		freearc(nfa, a);	}}/* * copyouts - copy all out arcs of a state to another state */static voidcopyouts(struct nfa * nfa,		 struct state * old,		 struct state * new){

⌨️ 快捷键说明

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