#include "regguts.h"
struct arcp {
struct sset *ss;
color co;
};
struct sset {
unsigned *states;
unsigned hash;
# define HASH(bv, nw) (((nw) == 1) ? *(bv) : hash(bv, nw))
# define HIT(h,bv,ss,nw) ((ss)->hash == (h) && ((nw) == 1 || \
memcmp(VS(bv), VS((ss)->states), (nw)*sizeof(unsigned)) == 0))
int flags;
# define STARTER 01
# define POSTSTATE 02
# define LOCKED 04
# define NOPROGRESS 010
struct arcp ins;
chr *lastseen;
struct sset **outs;
struct arcp *inchain;
};
struct dfa {
int nssets;
int nssused;
int nstates;
int ncolors;
int wordsper;
struct sset *ssets;
unsigned *statesarea;
unsigned *work;
struct sset **outsarea;
struct arcp *incarea;
struct cnfa *cnfa;
struct colormap *cm;
chr *lastpost;
chr *lastnopr;
struct sset *search;
int cptsmalloced;
char *mallocarea;
};
#define WORK 1
#define FEWSTATES 20
#define FEWCOLORS 15
struct smalldfa {
struct dfa dfa;
struct sset ssets[FEWSTATES*2];
unsigned statesarea[FEWSTATES*2 + WORK];
struct sset *outsarea[FEWSTATES*2 * FEWCOLORS];
struct arcp incarea[FEWSTATES*2 * FEWCOLORS];
};
#define DOMALLOC ((struct smalldfa *)NULL)
struct vars {
regex_t *re;
struct guts *g;
int eflags;
size_t nmatch;
regmatch_t *pmatch;
rm_detail_t *details;
chr *start;
chr *stop;
int err;
regoff_t *mem;
struct smalldfa dfa1;
struct smalldfa dfa2;
};
#define VISERR(vv) ((vv)->err != 0)
#define ISERR() VISERR(v)
#define VERR(vv,e) (((vv)->err) ? (vv)->err : ((vv)->err = (e)))
#define ERR(e) VERR(v, e)
#define NOERR() {if (ISERR()) return v->err;}
#define OFF(p) ((p) - v->start)
#define LOFF(p) ((long)OFF(p))
int exec _ANSI_ARGS_((regex_t *, CONST chr *, size_t, rm_detail_t *, size_t, regmatch_t [], int));
static int find _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *));
static int cfind _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *));
static int cfindloop _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *, struct dfa *, struct dfa *, chr **));
static VOID zapsubs _ANSI_ARGS_((regmatch_t *, size_t));
static VOID zapmem _ANSI_ARGS_((struct vars *, struct subre *));
static VOID subset _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
static int dissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
static int condissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
static int altdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
static int cdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
static int ccondissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
static int crevdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
static int cbrdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
static int caltdissect _ANSI_ARGS_((struct vars *, struct subre *, chr *, chr *));
static chr *longest _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *, int *));
static chr *shortest _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *, chr *, chr **, int *));
static chr *lastcold _ANSI_ARGS_((struct vars *, struct dfa *));
static struct dfa *newdfa _ANSI_ARGS_((struct vars *, struct cnfa *, struct colormap *, struct smalldfa *));
static VOID freedfa _ANSI_ARGS_((struct dfa *));
static unsigned hash _ANSI_ARGS_((unsigned *, int));
static struct sset *initialize _ANSI_ARGS_((struct vars *, struct dfa *, chr *));
static struct sset *miss _ANSI_ARGS_((struct vars *, struct dfa *, struct sset *, pcolor, chr *, chr *));
static int lacon _ANSI_ARGS_((struct vars *, struct cnfa *, chr *, pcolor));
static struct sset *getvacant _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *));
static struct sset *pickss _ANSI_ARGS_((struct vars *, struct dfa *, chr *, chr *));
int
exec(re, string, len, details, nmatch, pmatch, flags)
regex_t *re;
CONST chr *string;
size_t len;
rm_detail_t *details;
size_t nmatch;
regmatch_t pmatch[];
int flags;
{
struct vars var;
register struct vars *v = &var;
int st;
size_t n;
int backref;
# define LOCALMAT 20
regmatch_t mat[LOCALMAT];
# define LOCALMEM 40
regoff_t mem[LOCALMEM];
if (re == NULL || string == NULL || re->re_magic != REMAGIC)
return REG_INVARG;
if (re->re_csize != sizeof(chr))
return REG_MIXED;
v->re = re;
v->g = (struct guts *)re->re_guts;
if ((v->g->cflags®_EXPECT) && details == NULL)
return REG_INVARG;
if (v->g->info®_UIMPOSSIBLE)
return REG_NOMATCH;
backref = (v->g->info®_UBACKREF) ? 1 : 0;
v->eflags = flags;
if (v->g->cflags®_NOSUB)
nmatch = 0;
v->nmatch = nmatch;
if (backref) {
if (v->g->nsub + 1 <= LOCALMAT)
v->pmatch = mat;
else
v->pmatch = (regmatch_t *)MALLOC((v->g->nsub + 1) *
sizeof(regmatch_t));
if (v->pmatch == NULL)
return REG_ESPACE;
v->nmatch = v->g->nsub + 1;
} else
v->pmatch = pmatch;
v->details = details;
v->start = (chr *)string;
v->stop = (chr *)string + len;
v->err = 0;
if (backref) {
assert(v->g->ntree >= 0);
n = (size_t)v->g->ntree;
if (n <= LOCALMEM)
v->mem = mem;
else
v->mem = (regoff_t *)MALLOC(n*sizeof(regoff_t));
if (v->mem == NULL) {
if (v->pmatch != pmatch && v->pmatch != mat)
FREE(v->pmatch);
return REG_ESPACE;
}
} else
v->mem = NULL;
assert(v->g->tree != NULL);
if (backref)
st = cfind(v, &v->g->tree->cnfa, &v->g->cmap);
else
st = find(v, &v->g->tree->cnfa, &v->g->cmap);
if (st == REG_OKAY && v->pmatch != pmatch && nmatch > 0) {
zapsubs(pmatch, nmatch);
n = (nmatch < v->nmatch) ? nmatch : v->nmatch;
memcpy(VS(pmatch), VS(v->pmatch), n*sizeof(regmatch_t));
}
if (v->pmatch != pmatch && v->pmatch != mat)
FREE(v->pmatch);
if (v->mem != NULL && v->mem != mem)
FREE(v->mem);
return st;
}
static int
find(v, cnfa, cm)
struct vars *v;
struct cnfa *cnfa;
struct colormap *cm;
{
struct dfa *s;
struct dfa *d;
chr *begin;
chr *end = NULL;
chr *cold;
chr *open;
chr *close;
int hitend;
int shorter = (v->g->tree->flags&SHORTER) ? 1 : 0;
s = newdfa(v, &v->g->search, cm, &v->dfa1);
assert(!(ISERR() && s != NULL));
NOERR();
MDEBUG(("\nsearch at %ld\n", LOFF(v->start)));
cold = NULL;
close = shortest(v, s, v->start, v->start, v->stop, &cold, (int *)NULL);
freedfa(s);
NOERR();
if (v->g->cflags®_EXPECT) {
assert(v->details != NULL);
if (cold != NULL)
v->details->rm_extend.rm_so = OFF(cold);
else
v->details->rm_extend.rm_so = OFF(v->stop);
v->details->rm_extend.rm_eo = OFF(v->stop);
}
if (close == NULL)
return REG_NOMATCH;
if (v->nmatch == 0)
return REG_OKAY;
assert(cold != NULL);
open = cold;
cold = NULL;
MDEBUG(("between %ld and %ld\n", LOFF(open), LOFF(close)));
d = newdfa(v, cnfa, cm, &v->dfa1);
assert(!(ISERR() && d != NULL));
NOERR();
for (begin = open; begin <= close; begin++) {
MDEBUG(("\nfind trying at %ld\n", LOFF(begin)));
if (shorter)
end = shortest(v, d, begin, begin, v->stop,
(chr **)NULL, &hitend);
else
end = longest(v, d, begin, v->stop, &hitend);
NOERR();
if (hitend && cold == NULL)
cold = begin;
if (end != NULL)
break;
}
assert(end != NULL);
freedfa(d);
assert(v->nmatch > 0);
v->pmatch[0].rm_so = OFF(begin);
v->pmatch[0].rm_eo = OFF(end);
if (v->g->cflags®_EXPECT) {
if (cold != NULL)
v->details->rm_extend.rm_so = OFF(cold);
else
v->details->rm_extend.rm_so = OFF(v->stop);
v->details->rm_extend.rm_eo = OFF(v->stop);
}
if (v->nmatch == 1)
return REG_OKAY;
zapsubs(v->pmatch, v->nmatch);
return dissect(v, v->g->tree, begin, end);
}
static int
cfind(v, cnfa, cm)
struct vars *v;
struct cnfa *cnfa;
struct colormap *cm;
{
struct dfa *s;
struct dfa *d;
chr *cold;
int ret;
s = newdfa(v, &v->g->search, cm, &v->dfa1);
NOERR();
d = newdfa(v, cnfa, cm, &v->dfa2);
if (ISERR()) {
assert(d == NULL);
freedfa(s);
return v->err;
}
ret = cfindloop(v, cnfa, cm, d, s, &cold);
freedfa(d);
freedfa(s);
NOERR();
if (v->g->cflags®_EXPECT) {
assert(v->details != NULL);
if (cold != NULL)
v->details->rm_extend.rm_so = OFF(cold);
else
v->details->rm_extend.rm_so = OFF(v->stop);
v->details->rm_extend.rm_eo = OFF(v->stop);
}
return ret;
}
static int
cfindloop(v, cnfa, cm, d, s, coldp)
struct vars *v;
struct cnfa *cnfa;
struct colormap *cm;
struct dfa *d;
struct dfa *s;
chr **coldp;
{
chr *begin;
chr *end;
chr *cold;
chr *open;
chr *close;
chr *estart;
chr *estop;
int er;
int shorter = v->g->tree->flags&SHORTER;
int hitend;
assert(d != NULL && s != NULL);
cold = NULL;
close = v->start;
do {
MDEBUG(("\ncsearch at %ld\n", LOFF(close)));
close = shortest(v, s, close, close, v->stop, &cold, (int *)NULL);
if (close == NULL)
break;
assert(cold != NULL);
open = cold;
cold = NULL;
MDEBUG(("cbetween %ld and %ld\n", LOFF(open), LOFF(close)));
for (begin = open; begin <= close; begin++) {
MDEBUG(("\ncfind trying at %ld\n", LOFF(begin)));
estart = begin;
estop = v->stop;
for (;;) {
if (shorter)
end = shortest(v, d, begin, estart,
estop, (chr **)NULL, &hitend);
else
end = longest(v, d, begin, estop,
&hitend);
if (hitend && cold == NULL)
cold = begin;
if (end == NULL)
break;
MDEBUG(("tentative end %ld\n", LOFF(end)));
zapsubs(v->pmatch, v->nmatch);
zapmem(v, v->g->tree);
er = cdissect(v, v->g->tree, begin, end);
if (er == REG_OKAY) {
if (v->nmatch > 0) {
v->pmatch[0].rm_so = OFF(begin);
v->pmatch[0].rm_eo = OFF(end);
}
*coldp = cold;
return REG_OKAY;
}
if (er != REG_NOMATCH) {
ERR(er);
return er;
}
if ((shorter) ? end == estop : end == begin) {
*coldp = cold;
return REG_NOMATCH;
}
if (shorter)
estart = end + 1;
else
estop = end - 1;
}
}
} while (close < v->stop);
*coldp = cold;
return REG_NOMATCH;
}
static VOID
zapsubs(p, n)
regmatch_t *p;
size_t n;
{
size_t i;
for (i = n-1; i > 0; i--) {
p[i].rm_so = -1;
p[i].rm_eo = -1;
}
}
static VOID
zapmem(v, t)
struct vars *v;
struct subre *t;
{
if (t == NULL)
return;
assert(v->mem != NULL);
v->mem[t->retry] = 0;
if (t->op == '(') {
assert(t->subno > 0);
v->pmatch[t->subno].rm_so = -1;
v->pmatch[t->subno].rm_eo = -1;
}
if (t->left != NULL)
zapmem(v, t->left);
if (t->right != NULL)
zapmem(v, t->right);
}
static VOID
subset(v, sub, begin, end)
struct vars *v;
struct subre *sub;
chr *begin;
chr *end;
{
int n = sub->subno;
assert(n > 0);
if ((size_t)n >= v->nmatch)
return;
MDEBUG(("setting %d\n", n));
v->pmatch[n].rm_so = OFF(begin);
v->pmatch[n].rm_eo = OFF(end);
}
static int
dissect(v, t, begin, end)
struct vars *v;
struct subre *t;
chr *begin;
chr *end;
{
assert(t != NULL);
MDEBUG(("dissect %ld-%ld\n", LOFF(begin), LOFF(end)));
switch (t->op) {
case '=':
assert(t->left == NULL && t->right == NULL);
return REG_OKAY;
break;
case '|':
assert(t->left != NULL);
return altdissect(v, t, begin, end);
break;
case 'b':
return REG_ASSERT;
break;
case '.':
assert(t->left != NULL && t->right != NULL);
return condissect(v, t, begin, end);
break;
case '(':
assert(t->left != NULL && t->right == NULL);
assert(t->subno > 0);
subset(v, t, begin, end);
return dissect(v, t->left, begin, end);
break;
default:
return REG_ASSERT;
break;
}
}
static int
condissect(v, t, begin, end)
struct vars *v;
struct subre *t;
chr *begin;
chr *end;
{
struct dfa *d;
struct dfa *d2;
chr *mid;
int i;
int shorter = (t->left->flags&SHORTER) ? 1 : 0;
chr *stop = (shorter) ? end : begin;
assert(t->op == '.');
assert(t->left != NULL && t->left->cnfa.nstates > 0);
assert(t->right != NULL && t->right->cnfa.nstates > 0);
d = newdfa(v, &t->left->cnfa, &v->g->cmap, &v->dfa1);
NOERR();
d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, &v->dfa2);
if (ISERR()) {
assert(d2 == NULL);
freedfa(d);
return v->err;
}
if (shorter)
mid = shortest(v, d, begin, begin, end, (chr **)NULL,
(int *)NULL);
else
mid = longest(v, d, begin, end, (int *)NULL);
if (mid == NULL) {
freedfa(d);
freedfa(d2);
return REG_ASSERT;
}
MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
while (longest(v, d2, mid, end, (int *)NULL) != end) {
if (mid == stop) {
MDEBUG(("no midpoint!\n"));
freedfa(d);
freedfa(d2);
return REG_ASSERT;
}
if (shorter)
mid = shortest(v, d, begin, mid+1, end, (chr **)NULL,
(int *)NULL);
else
mid = longest(v, d, begin, mid-1, (int *)NULL);
if (mid == NULL) {
MDEBUG(("failed midpoint!\n"));
freedfa(d);
freedfa(d2);
return REG_ASSERT;
}
MDEBUG(("new midpoint %ld\n", LOFF(mid)));
}
MDEBUG(("successful\n"));
freedfa(d);
freedfa(d2);
i = dissect(v, t->left, begin, mid);
if (i != REG_OKAY)
return i;
return dissect(v, t->right, mid, end);
}
static int
altdissect(v, t, begin, end)
struct vars *v;
struct subre *t;
chr *begin;
chr *end;
{
struct dfa *d;
int i;
assert(t != NULL);
assert(t->op == '|');
for (i = 0; t != NULL; t = t->right, i++) {
MDEBUG(("trying %dth\n", i));
assert(t->left != NULL && t->left->cnfa.nstates > 0);
d = newdfa(v, &t->left->cnfa, &v->g->cmap, &v->dfa1);
if (ISERR())
return v->err;
if (longest(v, d, begin, end, (int *)NULL) == end) {
MDEBUG(("success\n"));
freedfa(d);
return dissect(v, t->left, begin, end);
}
freedfa(d);
}
return REG_ASSERT;
}
static int
cdissect(v, t, begin, end)
struct vars *v;
struct subre *t;
chr *begin;
chr *end;
{
int er;
assert(t != NULL);
MDEBUG(("cdissect %ld-%ld %c\n", LOFF(begin), LOFF(end), t->op));
switch (t->op) {
case '=':
assert(t->left == NULL && t->right == NULL);
return REG_OKAY;
break;
case '|':
assert(t->left != NULL);
return caltdissect(v, t, begin, end);
break;
case 'b':
assert(t->left == NULL && t->right == NULL);
return cbrdissect(v, t, begin, end);
break;
case '.':
assert(t->left != NULL && t->right != NULL);
return ccondissect(v, t, begin, end);
break;
case '(':
assert(t->left != NULL && t->right == NULL);
assert(t->subno > 0);
er = cdissect(v, t->left, begin, end);
if (er == REG_OKAY)
subset(v, t, begin, end);
return er;
break;
default:
return REG_ASSERT;
break;
}
}
static int
ccondissect(v, t, begin, end)
struct vars *v;
struct subre *t;
chr *begin;
chr *end;
{
struct dfa *d;
struct dfa *d2;
chr *mid;
int er;
assert(t->op == '.');
assert(t->left != NULL && t->left->cnfa.nstates > 0);
assert(t->right != NULL && t->right->cnfa.nstates > 0);
if (t->left->flags&SHORTER)
return crevdissect(v, t, begin, end);
d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
if (ISERR())
return v->err;
d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, DOMALLOC);
if (ISERR()) {
freedfa(d);
return v->err;
}
MDEBUG(("cconcat %d\n", t->retry));
if (v->mem[t->retry] == 0) {
mid = longest(v, d, begin, end, (int *)NULL);
if (mid == NULL) {
freedfa(d);
freedfa(d2);
return REG_NOMATCH;
}
MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
v->mem[t->retry] = (mid - begin) + 1;
} else {
mid = begin + (v->mem[t->retry] - 1);
MDEBUG(("working midpoint %ld\n", LOFF(mid)));
}
for (;;) {
er = cdissect(v, t->left, begin, mid);
if (er == REG_OKAY &&
longest(v, d2, mid, end, (int *)NULL) == end &&
(er = cdissect(v, t->right, mid, end)) ==
REG_OKAY)
break;
if (er != REG_OKAY && er != REG_NOMATCH) {
freedfa(d);
freedfa(d2);
return er;
}
if (mid == begin) {
MDEBUG(("%d no midpoint\n", t->retry));
freedfa(d);
freedfa(d2);
return REG_NOMATCH;
}
mid = longest(v, d, begin, mid-1, (int *)NULL);
if (mid == NULL) {
MDEBUG(("%d failed midpoint\n", t->retry));
freedfa(d);
freedfa(d2);
return REG_NOMATCH;
}
MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid)));
v->mem[t->retry] = (mid - begin) + 1;
zapmem(v, t->left);
zapmem(v, t->right);
}
MDEBUG(("successful\n"));
freedfa(d);
freedfa(d2);
return REG_OKAY;
}
static int
crevdissect(v, t, begin, end)
struct vars *v;
struct subre *t;
chr *begin;
chr *end;
{
struct dfa *d;
struct dfa *d2;
chr *mid;
int er;
assert(t->op == '.');
assert(t->left != NULL && t->left->cnfa.nstates > 0);
assert(t->right != NULL && t->right->cnfa.nstates > 0);
assert(t->left->flags&SHORTER);
d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
if (ISERR())
return v->err;
d2 = newdfa(v, &t->right->cnfa, &v->g->cmap, DOMALLOC);
if (ISERR()) {
freedfa(d);
return v->err;
}
MDEBUG(("crev %d\n", t->retry));
if (v->mem[t->retry] == 0) {
mid = shortest(v, d, begin, begin, end, (chr **)NULL, (int *)NULL);
if (mid == NULL) {
freedfa(d);
freedfa(d2);
return REG_NOMATCH;
}
MDEBUG(("tentative midpoint %ld\n", LOFF(mid)));
v->mem[t->retry] = (mid - begin) + 1;
} else {
mid = begin + (v->mem[t->retry] - 1);
MDEBUG(("working midpoint %ld\n", LOFF(mid)));
}
for (;;) {
er = cdissect(v, t->left, begin, mid);
if (er == REG_OKAY &&
longest(v, d2, mid, end, (int *)NULL) == end &&
(er = cdissect(v, t->right, mid, end)) ==
REG_OKAY)
break;
if (er != REG_OKAY && er != REG_NOMATCH) {
freedfa(d);
freedfa(d2);
return er;
}
if (mid == end) {
MDEBUG(("%d no midpoint\n", t->retry));
freedfa(d);
freedfa(d2);
return REG_NOMATCH;
}
mid = shortest(v, d, begin, mid+1, end, (chr **)NULL, (int *)NULL);
if (mid == NULL) {
MDEBUG(("%d failed midpoint\n", t->retry));
freedfa(d);
freedfa(d2);
return REG_NOMATCH;
}
MDEBUG(("%d: new midpoint %ld\n", t->retry, LOFF(mid)));
v->mem[t->retry] = (mid - begin) + 1;
zapmem(v, t->left);
zapmem(v, t->right);
}
MDEBUG(("successful\n"));
freedfa(d);
freedfa(d2);
return REG_OKAY;
}
static int
cbrdissect(v, t, begin, end)
struct vars *v;
struct subre *t;
chr *begin;
chr *end;
{
int i;
int n = t->subno;
size_t len;
chr *paren;
chr *p;
chr *stop;
int min = t->min;
int max = t->max;
assert(t != NULL);
assert(t->op == 'b');
assert(n >= 0);
assert((size_t)n < v->nmatch);
MDEBUG(("cbackref n%d %d{%d-%d}\n", t->retry, n, min, max));
if (v->pmatch[n].rm_so == -1)
return REG_NOMATCH;
paren = v->start + v->pmatch[n].rm_so;
len = v->pmatch[n].rm_eo - v->pmatch[n].rm_so;
if (v->mem[t->retry])
return REG_NOMATCH;
v->mem[t->retry] = 1;
if (len == 0) {
if (begin == end)
return REG_OKAY;
return REG_NOMATCH;
}
assert(end >= begin);
if ((size_t)(end - begin) < len)
return REG_NOMATCH;
stop = end - len;
i = 0;
for (p = begin; p <= stop && (i < max || max == INFINITY); p += len) {
if ((*v->g->compare)(paren, p, len) != 0)
break;
i++;
}
MDEBUG(("cbackref found %d\n", i));
if (p != end)
return REG_NOMATCH;
if (min <= i && (i <= max || max == INFINITY))
return REG_OKAY;
return REG_NOMATCH;
}
static int
caltdissect(v, t, begin, end)
struct vars *v;
struct subre *t;
chr *begin;
chr *end;
{
struct dfa *d;
int er;
# define UNTRIED 0
# define TRYING 1
# define TRIED 2
if (t == NULL)
return REG_NOMATCH;
assert(t->op == '|');
if (v->mem[t->retry] == TRIED)
return caltdissect(v, t->right, begin, end);
MDEBUG(("calt n%d\n", t->retry));
assert(t->left != NULL);
if (v->mem[t->retry] == UNTRIED) {
d = newdfa(v, &t->left->cnfa, &v->g->cmap, DOMALLOC);
if (ISERR())
return v->err;
if (longest(v, d, begin, end, (int *)NULL) != end) {
freedfa(d);
v->mem[t->retry] = TRIED;
return caltdissect(v, t->right, begin, end);
}
freedfa(d);
MDEBUG(("calt matched\n"));
v->mem[t->retry] = TRYING;
}
er = cdissect(v, t->left, begin, end);
if (er != REG_NOMATCH)
return er;
v->mem[t->retry] = TRIED;
return caltdissect(v, t->right, begin, end);
}
#include "rege_dfa.c"