aboutsummaryrefslogtreecommitdiff
path: root/src/backend/regex/regc_nfa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/regex/regc_nfa.c')
-rw-r--r--src/backend/regex/regc_nfa.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/backend/regex/regc_nfa.c b/src/backend/regex/regc_nfa.c
index 60fb0bec5d7..06bbcae0ee3 100644
--- a/src/backend/regex/regc_nfa.c
+++ b/src/backend/regex/regc_nfa.c
@@ -1490,6 +1490,7 @@ removetraverse(struct nfa *nfa,
{
case PLAIN:
case EMPTY:
+ case CANTMATCH:
/* nothing to do */
break;
case AHEAD:
@@ -1627,6 +1628,12 @@ optimize(struct nfa *nfa,
if (verbose)
fprintf(f, "\ninitial cleanup:\n");
#endif
+ /* If we have any CANTMATCH arcs, drop them; but this is uncommon */
+ if (nfa->flags & HASCANTMATCH)
+ {
+ removecantmatch(nfa);
+ nfa->flags &= ~HASCANTMATCH;
+ }
cleanup(nfa); /* may simplify situation */
#ifdef REG_DEBUG
if (verbose)
@@ -2951,6 +2958,34 @@ clonesuccessorstates(struct nfa *nfa,
}
/*
+ * removecantmatch - remove CANTMATCH arcs, which are no longer useful
+ * once we are done with the parsing phase. (We need them only to
+ * preserve connectedness of NFA subgraphs during parsing.)
+ */
+static void
+removecantmatch(struct nfa *nfa)
+{
+ struct state *s;
+
+ for (s = nfa->states; s != NULL; s = s->next)
+ {
+ struct arc *a;
+ struct arc *nexta;
+
+ for (a = s->outs; a != NULL; a = nexta)
+ {
+ nexta = a->outchain;
+ if (a->type == CANTMATCH)
+ {
+ freearc(nfa, a);
+ if (NISERR())
+ return;
+ }
+ }
+ }
+}
+
+/*
* cleanup - clean up NFA after optimizations
*/
static void
@@ -3659,6 +3694,8 @@ dumpnfa(struct nfa *nfa,
fprintf(f, ", eol [%ld]", (long) nfa->eos[1]);
if (nfa->flags & HASLACONS)
fprintf(f, ", haslacons");
+ if (nfa->flags & HASCANTMATCH)
+ fprintf(f, ", hascantmatch");
if (nfa->flags & MATCHALL)
{
fprintf(f, ", minmatchall %d", nfa->minmatchall);
@@ -3781,6 +3818,9 @@ dumparc(struct arc *a,
break;
case EMPTY:
break;
+ case CANTMATCH:
+ fprintf(f, "X");
+ break;
default:
fprintf(f, "0x%x/0%lo", a->type, (long) a->co);
break;