sam: revert regexp fix

This commit is contained in:
Russ Cox 2007-12-07 17:33:03 -05:00
parent 73778baeb3
commit 2deda14e42

View file

@ -527,56 +527,26 @@ classmatch(int classno, int c, int negate)
} }
/* /*
* Add inst to the list [l, l+NLIST), but only if it is not there already. * Note optimization in addinst:
* These work lists are stored and processed in increasing * *l must be pending when addinst called; if *l has been looked
* order of sep->p[0], so if the inst is there already, the one * at already, the optimization is a bug.
* there already is a more left match and takes priority.
* (This works for backward searches too, because there
* is no explicit comparison.)
*/ */
Ilist*
addinst1(Ilist *l, Inst *inst, Rangeset *sep)
{
Ilist *p;
for(p = l; p->inst; p++)
if(p->inst==inst)
return 0;
if(p == l+NLIST)
return l+NLIST;
p->inst = inst;
p->se = *sep;
(p+1)->inst = 0;
return p;
}
int int
addinst(Ilist *l, Inst *inst, Rangeset *sep) addinst(Ilist *l, Inst *inst, Rangeset *sep)
{ {
Ilist *ap; Ilist *p;
ap = addinst1(l, inst, sep); for(p = l; p->inst; p++){
if(ap == 0) if(p->inst==inst){
return 0; if((sep)->p[0].p1 < p->se.p[0].p1)
if(ap == l+NLIST) p->se= *sep; /* this would be bug */
return -1; return 0; /* It's already there */
/*
* Added inst to list at ap.
* Expand any ORs right now, so that entire
* work list ends up being sorted by increasing sep->p[0].
*/
for(; ap->inst; ap++){
if(ap->inst->type == OR){
if(addinst1(l, ap->inst->left, &ap->se) == l+NLIST)
return -1;
if(addinst1(l, ap->inst->right, &ap->se) == l+NLIST)
return -1;
} }
} }
return 0; p->inst = inst;
p->se= *sep;
(p+1)->inst = 0;
return 1;
} }
int int
@ -586,13 +556,13 @@ execute(File *f, Posn startp, Posn eof)
Inst *inst; Inst *inst;
Ilist *tlp; Ilist *tlp;
Posn p = startp; Posn p = startp;
int nnl = 0, ntl;
int c; int c;
int wrapped = 0; int wrapped = 0;
int startchar = startinst->type<OPERATOR? startinst->type : 0; int startchar = startinst->type<OPERATOR? startinst->type : 0;
list[0][0].inst = list[1][0].inst = 0; list[0][0].inst = list[1][0].inst = 0;
sel.p[0].p1 = -1; sel.p[0].p1 = -1;
nl = list[0];
/* Execute machine once for each character */ /* Execute machine once for each character */
for(;;p++){ for(;;p++){
doloop: doloop:
@ -611,18 +581,21 @@ execute(File *f, Posn startp, Posn eof)
default: default:
goto Return; goto Return;
} }
}else if(((wrapped && p>=startp) || sel.p[0].p1>0) && nl->inst==0) }else if(((wrapped && p>=startp) || sel.p[0].p1>0) && nnl==0)
break; break;
/* fast check for first char */ /* fast check for first char */
if(startchar && nl->inst==0 && c!=startchar) if(startchar && nnl==0 && c!=startchar)
continue; continue;
tl = list[flag]; tl = list[flag];
nl = list[flag^=1]; nl = list[flag^=1];
nl->inst = 0; nl->inst = 0;
ntl = nnl;
nnl = 0;
if(sel.p[0].p1<0 && (!wrapped || p<startp || startp==eof)){ if(sel.p[0].p1<0 && (!wrapped || p<startp || startp==eof)){
/* Add first instruction to this list */ /* Add first instruction to this list */
sempty.p[0].p1 = p; sempty.p[0].p1 = p;
if(addinst(tl, startinst, &sempty) < 0) if(addinst(tl, startinst, &sempty))
if(++ntl >= NLIST)
Overflow: Overflow:
error(Eoverflow); error(Eoverflow);
} }
@ -633,7 +606,8 @@ execute(File *f, Posn startp, Posn eof)
default: /* regular character */ default: /* regular character */
if(inst->type==c){ if(inst->type==c){
Addinst: Addinst:
if(addinst(nl, inst->next, &tlp->se) < 0) if(addinst(nl, inst->next, &tlp->se))
if(++nnl >= NLIST)
goto Overflow; goto Overflow;
} }
break; break;
@ -671,8 +645,13 @@ execute(File *f, Posn startp, Posn eof)
goto Addinst; goto Addinst;
break; break;
case OR: case OR:
/* already expanded; just a placeholder */ /* evaluate right choice later */
break; if(addinst(tl, inst->right, &tlp->se))
if(++ntl >= NLIST)
goto Overflow;
/* efficiency: advance and re-evaluate */
inst = inst->left;
goto Switchstmt;
case END: /* Match! */ case END: /* Match! */
tlp->se.p[0].p2 = p; tlp->se.p[0].p2 = p;
newmatch(&tlp->se); newmatch(&tlp->se);
@ -702,13 +681,13 @@ bexecute(File *f, Posn startp)
Inst *inst; Inst *inst;
Ilist *tlp; Ilist *tlp;
Posn p = startp; Posn p = startp;
int nnl = 0, ntl;
int c; int c;
int wrapped = 0; int wrapped = 0;
int startchar = bstartinst->type<OPERATOR? bstartinst->type : 0; int startchar = bstartinst->type<OPERATOR? bstartinst->type : 0;
list[0][0].inst = list[1][0].inst = 0; list[0][0].inst = list[1][0].inst = 0;
sel.p[0].p1= -1; sel.p[0].p1= -1;
nl = list[0];
/* Execute machine once for each character, including terminal NUL */ /* Execute machine once for each character, including terminal NUL */
for(;;--p){ for(;;--p){
doloop: doloop:
@ -727,18 +706,22 @@ bexecute(File *f, Posn startp)
default: default:
goto Return; goto Return;
} }
}else if(((wrapped && p<=startp) || sel.p[0].p1>0) && nl->inst==0) }else if(((wrapped && p<=startp) || sel.p[0].p1>0) && nnl==0)
break; break;
/* fast check for first char */ /* fast check for first char */
if(startchar && nl->inst==0 && c!=startchar) if(startchar && nnl==0 && c!=startchar)
continue; continue;
tl = list[flag]; tl = list[flag];
nl = list[flag^=1]; nl = list[flag^=1];
nl->inst = 0; nl->inst = 0;
ntl = nnl;
nnl = 0;
if(sel.p[0].p1<0 && (!wrapped || p>startp)){ if(sel.p[0].p1<0 && (!wrapped || p>startp)){
/* Add first instruction to this list */ /* Add first instruction to this list */
sempty.p[0].p1 = p; /* the minus is so the optimizations in addinst work */
if(addinst(tl, bstartinst, &sempty) < 0) sempty.p[0].p1 = -p;
if(addinst(tl, bstartinst, &sempty))
if(++ntl >= NLIST)
Overflow: Overflow:
error(Eoverflow); error(Eoverflow);
} }
@ -749,7 +732,8 @@ bexecute(File *f, Posn startp)
default: /* regular character */ default: /* regular character */
if(inst->type == c){ if(inst->type == c){
Addinst: Addinst:
if(addinst(nl, inst->next, &tlp->se) < 0) if(addinst(nl, inst->next, &tlp->se))
if(++nnl >= NLIST)
goto Overflow; goto Overflow;
} }
break; break;
@ -787,9 +771,15 @@ bexecute(File *f, Posn startp)
goto Addinst; goto Addinst;
break; break;
case OR: case OR:
/* already expanded; just a placeholder */ /* evaluate right choice later */
break; if(addinst(tl, inst->right, &tlp->se))
if(++ntl >= NLIST)
goto Overflow;
/* efficiency: advance and re-evaluate */
inst = inst->left;
goto Switchstmt;
case END: /* Match! */ case END: /* Match! */
tlp->se.p[0].p1 = -tlp->se.p[0].p1; /* minus sign */
tlp->se.p[0].p2 = p; tlp->se.p[0].p2 = p;
bnewmatch(&tlp->se); bnewmatch(&tlp->se);
break; break;