2011-03-30 12:46:40 +00:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
2016-04-27 03:23:44 +00:00
|
|
|
#include <regexp.h>
|
|
|
|
#include "regimpl.h"
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2016-04-27 03:23:44 +00:00
|
|
|
typedef struct RethreadQ RethreadQ;
|
2017-02-03 03:21:34 +00:00
|
|
|
struct RethreadQ {
|
2016-04-27 03:23:44 +00:00
|
|
|
Rethread *head;
|
|
|
|
Rethread **tail;
|
|
|
|
};
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2016-04-27 03:23:44 +00:00
|
|
|
int
|
2017-02-03 03:21:34 +00:00
|
|
|
regexec(Reprog *p, char *str, Resub *sem, int msize)
|
2011-03-30 12:46:40 +00:00
|
|
|
{
|
2016-04-27 03:23:44 +00:00
|
|
|
RethreadQ lists[2], *clist, *nlist, *tmp;
|
2017-02-03 03:21:34 +00:00
|
|
|
Rethread *t, *next, *pool, *avail;
|
|
|
|
Reinst *ci;
|
2016-04-27 03:23:44 +00:00
|
|
|
Rune r;
|
|
|
|
char *sp, *ep, endc;
|
2017-02-03 03:21:34 +00:00
|
|
|
int i, matchgen, gen;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2016-04-27 03:23:44 +00:00
|
|
|
if(msize > NSUBEXPM)
|
|
|
|
msize = NSUBEXPM;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2017-02-03 03:21:34 +00:00
|
|
|
if(p->startinst->gen != 0) {
|
|
|
|
for(ci = p->startinst; ci < p->startinst + p->len; ci++)
|
|
|
|
ci->gen = 0;
|
2016-04-27 03:23:44 +00:00
|
|
|
}
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2017-02-03 03:21:34 +00:00
|
|
|
memset(p->threads, 0, sizeof(Rethread)*p->nthr);
|
|
|
|
|
2016-04-27 03:23:44 +00:00
|
|
|
clist = lists;
|
|
|
|
clist->head = nil;
|
|
|
|
clist->tail = &clist->head;
|
|
|
|
nlist = lists + 1;
|
|
|
|
nlist->head = nil;
|
|
|
|
nlist->tail = &nlist->head;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2017-02-03 03:21:34 +00:00
|
|
|
pool = p->threads;
|
2016-04-27 22:36:43 +00:00
|
|
|
avail = nil;
|
2011-03-30 12:46:40 +00:00
|
|
|
|
2017-02-03 03:21:34 +00:00
|
|
|
gen = matchgen = 0;
|
2016-04-27 03:23:44 +00:00
|
|
|
sp = str;
|
|
|
|
ep = nil;
|
|
|
|
endc = '\0';
|
|
|
|
if(sem != nil && msize > 0) {
|
|
|
|
if(sem->sp != nil)
|
|
|
|
sp = sem->sp;
|
|
|
|
if(sem->ep != nil && *sem->ep != '\0') {
|
|
|
|
ep = sem->ep;
|
|
|
|
endc = *sem->ep;
|
|
|
|
*sem->ep = '\0';
|
|
|
|
}
|
|
|
|
}
|
2017-02-03 03:21:34 +00:00
|
|
|
for(r = 1; r != L'\0'; sp += i) {
|
2016-04-27 03:23:44 +00:00
|
|
|
i = chartorune(&r, sp);
|
2017-02-03 03:21:34 +00:00
|
|
|
gen++;
|
|
|
|
if(matchgen == 0) {
|
|
|
|
if(avail == nil) {
|
|
|
|
assert(pool < p->threads + p->nthr);
|
|
|
|
t = pool++;
|
|
|
|
} else {
|
|
|
|
t = avail;
|
|
|
|
avail = avail->next;
|
|
|
|
}
|
|
|
|
t->i = p->startinst;
|
|
|
|
if(msize > 0)
|
|
|
|
memset(t->sem, 0, sizeof(Resub)*msize);
|
|
|
|
t->next = nil;
|
|
|
|
t->gen = gen;
|
|
|
|
*clist->tail = t;
|
|
|
|
clist->tail = &t->next;
|
|
|
|
}
|
2016-04-27 03:23:44 +00:00
|
|
|
t = clist->head;
|
|
|
|
if(t == nil)
|
2017-02-03 03:21:34 +00:00
|
|
|
break;
|
|
|
|
ci = t->i;
|
2016-04-27 03:23:44 +00:00
|
|
|
Again:
|
2017-02-03 03:21:34 +00:00
|
|
|
if(ci->gen == gen || matchgen && t->gen > matchgen)
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Done;
|
2017-02-03 03:21:34 +00:00
|
|
|
ci->gen = gen;
|
|
|
|
switch(ci->op) {
|
2016-04-27 03:23:44 +00:00
|
|
|
case ORUNE:
|
2017-02-03 03:21:34 +00:00
|
|
|
if(r != ci->r)
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Done;
|
|
|
|
case OANY: /* fallthrough */
|
2016-04-27 22:36:43 +00:00
|
|
|
next = t->next;
|
2017-02-03 03:21:34 +00:00
|
|
|
t->i = ci + 1;
|
2016-04-27 03:23:44 +00:00
|
|
|
t->next = nil;
|
|
|
|
*nlist->tail = t;
|
|
|
|
nlist->tail = &t->next;
|
2016-04-27 22:36:43 +00:00
|
|
|
if(next == nil)
|
2016-04-27 03:23:44 +00:00
|
|
|
break;
|
2016-04-27 22:36:43 +00:00
|
|
|
t = next;
|
2017-02-03 03:21:34 +00:00
|
|
|
ci = t->i;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
|
|
|
case OCLASS:
|
|
|
|
Class:
|
2017-02-03 03:21:34 +00:00
|
|
|
if(r < ci->r)
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Done;
|
2017-02-03 03:21:34 +00:00
|
|
|
if(r > ci->r1) {
|
|
|
|
ci++;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Class;
|
|
|
|
}
|
2016-04-27 22:36:43 +00:00
|
|
|
next = t->next;
|
2017-02-03 03:21:34 +00:00
|
|
|
t->i = ci->a;
|
2016-04-27 03:23:44 +00:00
|
|
|
t->next = nil;
|
|
|
|
*nlist->tail = t;
|
|
|
|
nlist->tail = &t->next;
|
2016-04-27 22:36:43 +00:00
|
|
|
if(next == nil)
|
2011-03-30 12:46:40 +00:00
|
|
|
break;
|
2016-04-27 22:36:43 +00:00
|
|
|
t = next;
|
2017-02-03 03:21:34 +00:00
|
|
|
ci = t->i;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
|
|
|
case ONOTNL:
|
|
|
|
if(r != L'\n') {
|
2017-02-03 03:21:34 +00:00
|
|
|
ci++;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
|
|
|
}
|
|
|
|
goto Done;
|
|
|
|
case OBOL:
|
|
|
|
if(sp == str || sp[-1] == '\n') {
|
2017-02-03 03:21:34 +00:00
|
|
|
ci++;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Done;
|
|
|
|
case OEOL:
|
2016-05-01 01:03:12 +00:00
|
|
|
if(r == L'\n' || r == L'\0' && ep == nil) {
|
2017-02-03 03:21:34 +00:00
|
|
|
ci++;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
|
|
|
}
|
|
|
|
goto Done;
|
|
|
|
case OJMP:
|
2017-02-03 03:21:34 +00:00
|
|
|
ci = ci->a;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
|
|
|
case OSPLIT:
|
2017-02-03 03:21:34 +00:00
|
|
|
if(avail == nil) {
|
|
|
|
assert(pool < p->threads + p->nthr);
|
|
|
|
next = pool++;
|
|
|
|
} else {
|
2016-04-27 22:36:43 +00:00
|
|
|
next = avail;
|
|
|
|
avail = avail->next;
|
|
|
|
}
|
2017-02-03 03:21:34 +00:00
|
|
|
next->i = ci->b;
|
2016-04-27 03:23:44 +00:00
|
|
|
if(msize > 0)
|
2016-04-27 22:36:43 +00:00
|
|
|
memcpy(next->sem, t->sem, sizeof(Resub)*msize);
|
|
|
|
next->next = t->next;
|
2017-02-03 03:21:34 +00:00
|
|
|
next->gen = t->gen;
|
2016-04-27 22:36:43 +00:00
|
|
|
t->next = next;
|
2017-02-03 03:21:34 +00:00
|
|
|
ci = ci->a;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
|
|
|
case OSAVE:
|
2017-02-03 03:21:34 +00:00
|
|
|
if(ci->sub < msize)
|
|
|
|
t->sem[ci->sub].sp = sp;
|
|
|
|
ci++;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
|
|
|
case OUNSAVE:
|
2017-02-03 03:21:34 +00:00
|
|
|
if(ci->sub == 0) {
|
|
|
|
matchgen = t->gen;
|
2016-04-27 03:23:44 +00:00
|
|
|
if(sem != nil && msize > 0) {
|
|
|
|
memcpy(sem, t->sem, sizeof(Resub)*msize);
|
|
|
|
sem->ep = sp;
|
|
|
|
}
|
|
|
|
goto Done;
|
|
|
|
}
|
2017-02-03 03:21:34 +00:00
|
|
|
if(ci->sub < msize)
|
|
|
|
t->sem[ci->sub].ep = sp;
|
|
|
|
ci++;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
|
|
|
Done:
|
2016-04-27 22:36:43 +00:00
|
|
|
next = t->next;
|
|
|
|
t->next = avail;
|
|
|
|
avail = t;
|
|
|
|
if(next == nil)
|
2016-04-27 03:23:44 +00:00
|
|
|
break;
|
2016-04-27 22:36:43 +00:00
|
|
|
t = next;
|
2017-02-03 03:21:34 +00:00
|
|
|
ci = t->i;
|
2016-04-27 03:23:44 +00:00
|
|
|
goto Again;
|
|
|
|
}
|
|
|
|
tmp = clist;
|
|
|
|
clist = nlist;
|
|
|
|
nlist = tmp;
|
|
|
|
nlist->head = nil;
|
|
|
|
nlist->tail = &nlist->head;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|
2016-04-27 03:23:44 +00:00
|
|
|
if(ep != nil)
|
|
|
|
*ep = endc;
|
2017-02-03 03:21:34 +00:00
|
|
|
return matchgen > 0 ? 1 : 0;
|
2011-03-30 12:46:40 +00:00
|
|
|
}
|