📄 rege_dfa.c
字号:
/* * DFA routines * This file is #included by regexec.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/rege_dfa.c,v 1.8 2007/10/06 16:05:54 tgl Exp $ * *//* * longest - longest-preferred matching engine */static chr * /* endpoint, or NULL */longest(struct vars * v, /* used only for debug and exec flags */ struct dfa * d, chr *start, /* where the match should start */ chr *stop, /* match must end at or before here */ int *hitstopp) /* record whether hit v->stop, if non-NULL */{ chr *cp; chr *realstop = (stop == v->stop) ? stop : stop + 1; color co; struct sset *css; struct sset *ss; chr *post; int i; struct colormap *cm = d->cm; /* initialize */ css = initialize(v, d, start); cp = start; if (hitstopp != NULL) *hitstopp = 0; /* startup */ FDEBUG(("+++ startup +++\n")); if (cp == v->start) { co = d->cnfa->bos[(v->eflags & REG_NOTBOL) ? 0 : 1]; FDEBUG(("color %ld\n", (long) co)); } else { co = GETCOLOR(cm, *(cp - 1)); FDEBUG(("char %c, color %ld\n", (char) *(cp - 1), (long) co)); } css = miss(v, d, css, co, cp, start); if (css == NULL) return NULL; css->lastseen = cp; /* main loop */ if (v->eflags & REG_FTRACE) while (cp < realstop) { FDEBUG(("+++ at c%d +++\n", (int) (css - d->ssets))); co = GETCOLOR(cm, *cp); FDEBUG(("char %c, color %ld\n", (char) *cp, (long) co)); ss = css->outs[co]; if (ss == NULL) { ss = miss(v, d, css, co, cp + 1, start); if (ss == NULL) break; /* NOTE BREAK OUT */ } cp++; ss->lastseen = cp; css = ss; } else while (cp < realstop) { co = GETCOLOR(cm, *cp); ss = css->outs[co]; if (ss == NULL) { ss = miss(v, d, css, co, cp + 1, start); if (ss == NULL) break; /* NOTE BREAK OUT */ } cp++; ss->lastseen = cp; css = ss; } /* shutdown */ FDEBUG(("+++ shutdown at c%d +++\n", (int) (css - d->ssets))); if (cp == v->stop && stop == v->stop) { if (hitstopp != NULL) *hitstopp = 1; co = d->cnfa->eos[(v->eflags & REG_NOTEOL) ? 0 : 1]; FDEBUG(("color %ld\n", (long) co)); ss = miss(v, d, css, co, cp, start); /* special case: match ended at eol? */ if (ss != NULL && (ss->flags & POSTSTATE)) return cp; else if (ss != NULL) ss->lastseen = cp; /* to be tidy */ } /* find last match, if any */ post = d->lastpost; for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) if ((ss->flags & POSTSTATE) && post != ss->lastseen && (post == NULL || post < ss->lastseen)) post = ss->lastseen; if (post != NULL) /* found one */ return post - 1; return NULL;}/* * shortest - shortest-preferred matching engine */static chr * /* endpoint, or NULL */shortest(struct vars * v, struct dfa * d, chr *start, /* where the match should start */ chr *min, /* match must end at or after here */ chr *max, /* match must end at or before here */ chr **coldp, /* store coldstart pointer here, if nonNULL */ int *hitstopp) /* record whether hit v->stop, if non-NULL */{ chr *cp; chr *realmin = (min == v->stop) ? min : min + 1; chr *realmax = (max == v->stop) ? max : max + 1; color co; struct sset *css; struct sset *ss; struct colormap *cm = d->cm; /* initialize */ css = initialize(v, d, start); cp = start; if (hitstopp != NULL) *hitstopp = 0; /* startup */ FDEBUG(("--- startup ---\n")); if (cp == v->start) { co = d->cnfa->bos[(v->eflags & REG_NOTBOL) ? 0 : 1]; FDEBUG(("color %ld\n", (long) co)); } else { co = GETCOLOR(cm, *(cp - 1)); FDEBUG(("char %c, color %ld\n", (char) *(cp - 1), (long) co)); } css = miss(v, d, css, co, cp, start); if (css == NULL) return NULL; css->lastseen = cp; ss = css; /* main loop */ if (v->eflags & REG_FTRACE) while (cp < realmax) { FDEBUG(("--- at c%d ---\n", (int) (css - d->ssets))); co = GETCOLOR(cm, *cp); FDEBUG(("char %c, color %ld\n", (char) *cp, (long) co)); ss = css->outs[co]; if (ss == NULL) { ss = miss(v, d, css, co, cp + 1, start); if (ss == NULL) break; /* NOTE BREAK OUT */ } cp++; ss->lastseen = cp; css = ss; if ((ss->flags & POSTSTATE) && cp >= realmin) break; /* NOTE BREAK OUT */ } else while (cp < realmax) { co = GETCOLOR(cm, *cp); ss = css->outs[co]; if (ss == NULL) { ss = miss(v, d, css, co, cp + 1, start); if (ss == NULL) break; /* NOTE BREAK OUT */ } cp++; ss->lastseen = cp; css = ss; if ((ss->flags & POSTSTATE) && cp >= realmin) break; /* NOTE BREAK OUT */ } if (ss == NULL) return NULL; if (coldp != NULL) /* report last no-progress state set, if any */ *coldp = lastcold(v, d); if ((ss->flags & POSTSTATE) && cp > min) { assert(cp >= realmin); cp--; } else if (cp == v->stop && max == v->stop) { co = d->cnfa->eos[(v->eflags & REG_NOTEOL) ? 0 : 1]; FDEBUG(("color %ld\n", (long) co)); ss = miss(v, d, css, co, cp, start); /* match might have ended at eol */ if ((ss == NULL || !(ss->flags & POSTSTATE)) && hitstopp != NULL) *hitstopp = 1; } if (ss == NULL || !(ss->flags & POSTSTATE)) return NULL; return cp;}/* * lastcold - determine last point at which no progress had been made */static chr * /* endpoint, or NULL */lastcold(struct vars * v, struct dfa * d){ struct sset *ss; chr *nopr; int i; nopr = d->lastnopr; if (nopr == NULL) nopr = v->start; for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) if ((ss->flags & NOPROGRESS) && nopr < ss->lastseen) nopr = ss->lastseen; return nopr;}/* * newdfa - set up a fresh DFA */static struct dfa *newdfa(struct vars * v, struct cnfa * cnfa, struct colormap * cm, struct smalldfa * small) /* preallocated space, may be NULL */{ struct dfa *d; size_t nss = cnfa->nstates * 2; int wordsper = (cnfa->nstates + UBITS - 1) / UBITS; struct smalldfa *smallwas = small; assert(cnfa != NULL && cnfa->nstates != 0); if (nss <= FEWSTATES && cnfa->ncolors <= FEWCOLORS) { assert(wordsper == 1); if (small == NULL) { small = (struct smalldfa *) MALLOC( sizeof(struct smalldfa)); if (small == NULL) { ERR(REG_ESPACE); return NULL; } } d = &small->dfa; d->ssets = small->ssets; d->statesarea = small->statesarea; d->work = &d->statesarea[nss]; d->outsarea = small->outsarea; d->incarea = small->incarea; d->cptsmalloced = 0; d->mallocarea = (smallwas == NULL) ? (char *) small : NULL; } else { d = (struct dfa *) MALLOC(sizeof(struct dfa)); if (d == NULL) { ERR(REG_ESPACE); return NULL; } d->ssets = (struct sset *) MALLOC(nss * sizeof(struct sset)); d->statesarea = (unsigned *) MALLOC((nss + WORK) * wordsper * sizeof(unsigned)); d->work = &d->statesarea[nss * wordsper]; d->outsarea = (struct sset **) MALLOC(nss * cnfa->ncolors * sizeof(struct sset *)); d->incarea = (struct arcp *) MALLOC(nss * cnfa->ncolors * sizeof(struct arcp)); d->cptsmalloced = 1; d->mallocarea = (char *) d; if (d->ssets == NULL || d->statesarea == NULL || d->outsarea == NULL || d->incarea == NULL) { freedfa(d); ERR(REG_ESPACE); return NULL; } } d->nssets = (v->eflags & REG_SMALL) ? 7 : nss; d->nssused = 0; d->nstates = cnfa->nstates; d->ncolors = cnfa->ncolors; d->wordsper = wordsper; d->cnfa = cnfa; d->cm = cm; d->lastpost = NULL; d->lastnopr = NULL; d->search = d->ssets; /* initialization of sset fields is done as needed */ return d;}/* * freedfa - free a DFA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -