commit 2deda14e4268e7e8af4910d453db73e210d3eb58 from: Russ Cox date: Fri Dec 07 22:33:03 2007 UTC sam: revert regexp fix commit - 73778baeb38089772a806e6c2335f7ad6adb19a9 commit + 2deda14e4268e7e8af4910d453db73e210d3eb58 blob - b213d2f3cb5251340c93d68d7d4d3fc1b2b20e3d blob + 8beaa036dc1889e0c49f509f543f88132ab0cec6 --- src/cmd/sam/regexp.c +++ src/cmd/sam/regexp.c @@ -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. - * These work lists are stored and processed in increasing - * order of sep->p[0], so if the inst is there already, the one - * there already is a more left match and takes priority. - * (This works for backward searches too, because there - * is no explicit comparison.) + * Note optimization in addinst: + * *l must be pending when addinst called; if *l has been looked + * at already, the optimization is a bug. */ -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 addinst(Ilist *l, Inst *inst, Rangeset *sep) { - Ilist *ap; - - ap = addinst1(l, inst, sep); - if(ap == 0) - return 0; - if(ap == l+NLIST) - return -1; - - /* - * 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; + Ilist *p; + + for(p = l; p->inst; p++){ + if(p->inst==inst){ + if((sep)->p[0].p1 < p->se.p[0].p1) + p->se= *sep; /* this would be bug */ + return 0; /* It's already there */ } } - return 0; + p->inst = inst; + p->se= *sep; + (p+1)->inst = 0; + return 1; } int @@ -586,13 +556,13 @@ execute(File *f, Posn startp, Posn eof) Inst *inst; Ilist *tlp; Posn p = startp; + int nnl = 0, ntl; int c; int wrapped = 0; int startchar = startinst->typetype : 0; list[0][0].inst = list[1][0].inst = 0; sel.p[0].p1 = -1; - nl = list[0]; /* Execute machine once for each character */ for(;;p++){ doloop: @@ -611,18 +581,21 @@ execute(File *f, Posn startp, Posn eof) default: 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; /* fast check for first char */ - if(startchar && nl->inst==0 && c!=startchar) + if(startchar && nnl==0 && c!=startchar) continue; tl = list[flag]; nl = list[flag^=1]; nl->inst = 0; + ntl = nnl; + nnl = 0; if(sel.p[0].p1<0 && (!wrapped || p= NLIST) Overflow: error(Eoverflow); } @@ -633,7 +606,8 @@ execute(File *f, Posn startp, Posn eof) default: /* regular character */ if(inst->type==c){ Addinst: - if(addinst(nl, inst->next, &tlp->se) < 0) + if(addinst(nl, inst->next, &tlp->se)) + if(++nnl >= NLIST) goto Overflow; } break; @@ -671,8 +645,13 @@ execute(File *f, Posn startp, Posn eof) goto Addinst; break; case OR: - /* already expanded; just a placeholder */ - break; + /* evaluate right choice later */ + 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! */ tlp->se.p[0].p2 = p; newmatch(&tlp->se); @@ -702,13 +681,13 @@ bexecute(File *f, Posn startp) Inst *inst; Ilist *tlp; Posn p = startp; + int nnl = 0, ntl; int c; int wrapped = 0; int startchar = bstartinst->typetype : 0; list[0][0].inst = list[1][0].inst = 0; sel.p[0].p1= -1; - nl = list[0]; /* Execute machine once for each character, including terminal NUL */ for(;;--p){ doloop: @@ -727,18 +706,22 @@ bexecute(File *f, Posn startp) default: 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; /* fast check for first char */ - if(startchar && nl->inst==0 && c!=startchar) + if(startchar && nnl==0 && c!=startchar) continue; tl = list[flag]; nl = list[flag^=1]; nl->inst = 0; + ntl = nnl; + nnl = 0; if(sel.p[0].p1<0 && (!wrapped || p>startp)){ /* Add first instruction to this list */ - sempty.p[0].p1 = p; - if(addinst(tl, bstartinst, &sempty) < 0) + /* the minus is so the optimizations in addinst work */ + sempty.p[0].p1 = -p; + if(addinst(tl, bstartinst, &sempty)) + if(++ntl >= NLIST) Overflow: error(Eoverflow); } @@ -749,7 +732,8 @@ bexecute(File *f, Posn startp) default: /* regular character */ if(inst->type == c){ Addinst: - if(addinst(nl, inst->next, &tlp->se) < 0) + if(addinst(nl, inst->next, &tlp->se)) + if(++nnl >= NLIST) goto Overflow; } break; @@ -787,9 +771,15 @@ bexecute(File *f, Posn startp) goto Addinst; break; case OR: - /* already expanded; just a placeholder */ - break; + /* evaluate right choice later */ + 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! */ + tlp->se.p[0].p1 = -tlp->se.p[0].p1; /* minus sign */ tlp->se.p[0].p2 = p; bnewmatch(&tlp->se); break;