#include <stdlib.h>
#include <stdio.h>
#include "regexp.h"
#include "regcomp.h"
static Resublist sempty; /* empty set of matches */
/*
* return 0 if no match
* >0 if a match
* <0 if we ran out of _relist space
*/
static int
rregexec1(Reprog *progp, /* program to run */
wchar_t *bol, /* string to run machine on */
Resub *mp, /* subexpression elements */
int ms, /* number of elements at mp */
wchar_t *starts,
wchar_t *eol,
wchar_t startchar)
{
int flag=0;
Reinst *inst;
Relist *tlp;
wchar_t *s;
int i, checkstart;
wchar_t r, *rp, *ep;
Relist* tl; /* This list, next list */
Relist* nl;
Relist* tle; /* ends of this and next list */
Relist* nle;
int match;
match = 0;
checkstart = startchar;
sempty.m[0].s.rsp = 0;
if(mp!=0)
for(i=0; i<ms; i++)
mp[i].s.rsp = mp[i].e.rep = 0;
_relist[0][0].inst = _relist[1][0].inst = 0;
/* Execute machine once for each character, including terminal NUL */
s = starts;
do{
r = *s;
/* fast check for first char */
if(checkstart && r!=startchar){
s++;
continue;
}
/* switch run lists */
tl = _relist[flag];
tle = _reliste[flag];
nl = _relist[flag^=1];
nle = _reliste[flag];
nl->inst = 0;
/* Add first instruction to current list */
sempty.m[0].s.rsp = s;
_renewthread(tl, progp->startinst, &sempty);
/* Execute machine until current list is empty */
for(tlp=tl; tlp->inst; tlp++){ /* assignment = */
if(s == eol)
break;
for(inst=tlp->inst; ; inst = inst->l.next){
switch(inst->type){
case RUNE: /* regular character */
if(inst->r.r == r)
if(_renewthread(nl, inst->l.next, &tlp->se)==nle)
return -1;
break;
case LBRA:
tlp->se.m[inst->r.subid].s.rsp = s;
continue;
case RBRA:
tlp->se.m[inst->r.subid].e.rep = s;
continue;
case ANY:
if(r != '\n')
if(_renewthread(nl, inst->l.next, &tlp->se)==nle)
return -1;
break;
case ANYNL:
if(_renewthread(nl, inst->l.next, &tlp->se)==nle)
return -1;
break;
case BOL:
if(s == bol || *(s-1) == '\n')
continue;
break;
case EOL:
if(r == 0 || r == '\n')
continue;
break;
case CCLASS:
ep = inst->r.cp->end;
for(rp = inst->r.cp->spans; rp < ep; rp += 2)
if(r >= rp[0] && r <= rp[1]){
if(_renewthread(nl, inst->l.next, &tlp->se)==nle)
return -1;
break;
}
break;
case NCCLASS:
ep = inst->r.cp->end;
for(rp = inst->r.cp->spans; rp < ep; rp += 2)
if(r >= rp[0] && r <= rp[1])
break;
if(rp == ep)
if(_renewthread(nl, inst->l.next, &tlp->se)==nle)
return -1;
break;
case OR:
/* evaluate right choice later */
if(_renewthread(tlp, inst->r.right, &tlp->se) == tle)
return -1;
/* efficiency: advance and re-evaluate */
continue;
case END: /* Match! */
match = 1;
tlp->se.m[0].e.rep = s;
if(mp != 0)
_renewmatch(mp, ms, &tlp->se);
break;
}
break;
}
}
checkstart = startchar && nl->inst==0;
s++;
}while(r);
return match;
}
extern int
rregexec(Reprog *progp, /* program to run */
wchar_t *bol, /* string to run machine on */
Resub *mp, /* subexpression elements */
int ms) /* number of elements at mp */
{
wchar_t *starts; /* where to start match */
wchar_t *eol; /* where to end match */
wchar_t startchar;
int rv;
/*
* use user-specified starting/ending location if specified
*/
starts = bol;
eol = 0;
if(mp && ms>0){
if(mp->s.rsp)
starts = mp->s.rsp;
if(mp->e.rep)
eol = mp->e.rep;
}
startchar = progp->startinst->type == RUNE ? progp->startinst->r.r : 0;
/* keep trying till we have enough list space to terminate */
for(;;){
if(_relist[0] == 0){
_relist[0] = malloc(2*_relistsize*sizeof(Relist));
_relist[1] = _relist[0] + _relistsize;
_reliste[0] = _relist[0] + _relistsize - 1;
_reliste[1] = _relist[1] + _relistsize - 1;
if(_relist[0] == 0)
regerror("_relist overflow");
}
rv = rregexec1(progp, bol, mp, ms, starts, eol, startchar);
if(rv >= 0)
return rv;
free(_relist[0]);
_relist[0] = 0;
_relistsize += LISTINCREMENT;
}
}
|