}
}
+/*
+ * removeconstraints - remove any constraints in an NFA
+ *
+ * Constraint arcs are replaced by empty arcs, essentially treating all
+ * constraints as automatically satisfied.
+ */
+static void
+removeconstraints(struct nfa *nfa,
+ struct state *start, /* process subNFA starting here */
+ struct state *stop) /* and stopping here */
+{
+ if (start == stop)
+ return;
+
+ stop->tmp = stop;
+ removetraverse(nfa, start);
+ /* done, except for clearing out the tmp pointers */
+
+ stop->tmp = NULL;
+ cleartraverse(nfa, start);
+}
+
+/*
+ * removetraverse - recursive heart of removeconstraints
+ */
+static void
+removetraverse(struct nfa *nfa,
+ struct state *s)
+{
+ struct arc *a;
+ struct arc *oa;
+
+ /* Since this is recursive, it could be driven to stack overflow */
+ if (STACK_TOO_DEEP(nfa->v->re))
+ {
+ NERR(REG_ETOOBIG);
+ return;
+ }
+
+ if (s->tmp != NULL)
+ return; /* already done */
+
+ s->tmp = s;
+ for (a = s->outs; a != NULL && !NISERR(); a = oa)
+ {
+ removetraverse(nfa, a->to);
+ if (NISERR())
+ break;
+ oa = a->outchain;
+ switch (a->type)
+ {
+ case PLAIN:
+ case EMPTY:
+ /* nothing to do */
+ break;
+ case AHEAD:
+ case BEHIND:
+ case '^':
+ case '$':
+ case LACON:
+ /* replace it */
+ newarc(nfa, EMPTY, 0, s, a->to);
+ freearc(nfa, a);
+ break;
+ default:
+ NERR(REG_ASSERT);
+ break;
+ }
+ }
+}
+
/*
* cleartraverse - recursive cleanup for algorithms that leave tmp ptrs set
*/
static void deltraverse(struct nfa *, struct state *, struct state *);
static void dupnfa(struct nfa *, struct state *, struct state *, struct state *, struct state *);
static void duptraverse(struct nfa *, struct state *, struct state *);
+static void removeconstraints(struct nfa *, struct state *, struct state *);
+static void removetraverse(struct nfa *, struct state *);
static void cleartraverse(struct nfa *, struct state *);
static struct state *single_color_transition(struct state *, struct state *);
static void specialcolors(struct nfa *);
dupnfa(v->nfa, v->subs[subno]->begin, v->subs[subno]->end,
atom->begin, atom->end);
NOERR();
+
+ /* The backref node's NFA should not enforce any constraints */
+ removeconstraints(v->nfa, atom->begin, atom->end);
+ NOERR();
}
/*
{2,REG_UBACKREF,REG_UNONPOSIX}
(1 row)
+-- back reference only matches the string, not any constraints
+select * from test_regex('(^\w+).*\1', 'abc abc abc', 'LRP');
+ test_regex
+--------------------------------------------
+ {1,REG_UBACKREF,REG_UNONPOSIX,REG_ULOCALE}
+ {"abc abc abc",abc}
+(2 rows)
+
+select * from test_regex('(^\w+\M).*\1', 'abc abcd abd', 'LRP');
+ test_regex
+--------------------------------------------
+ {1,REG_UBACKREF,REG_UNONPOSIX,REG_ULOCALE}
+ {"abc abc",abc}
+(2 rows)
+
+select * from test_regex('(\w+(?= )).*\1', 'abc abcd abd', 'HLRP');
+ test_regex
+------------------------------------------------------------
+ {1,REG_UBACKREF,REG_ULOOKAROUND,REG_UNONPOSIX,REG_ULOCALE}
+ {"abc abc",abc}
+(2 rows)
+
-- doing 15 "octal escapes vs back references"
-- # initial zero is always octal
-- expectMatch 15.1 MP "a\\010b" "a\bb" "a\bb"
-- expectNomatch 14.29 RP {^(.+)( \1)+$} {abc abc abd}
select * from test_regex('^(.+)( \1)+$', 'abc abc abd', 'RP');
+-- back reference only matches the string, not any constraints
+select * from test_regex('(^\w+).*\1', 'abc abc abc', 'LRP');
+select * from test_regex('(^\w+\M).*\1', 'abc abcd abd', 'LRP');
+select * from test_regex('(\w+(?= )).*\1', 'abc abcd abd', 'HLRP');
+
-- doing 15 "octal escapes vs back references"
-- # initial zero is always octal