- /* Execute machine until current list is empty */
- for(tlp=tl; tlp->inst; tlp++){ /* assignment = */
- for(inst = tlp->inst; ; inst = inst->next){
- switch(inst->type){
- case RUNE: /* regular character */
- if(inst->r == r){
- if(_renewthread(nl, inst->next, ms, &tlp->se)==nle)
- return -1;
- }
- break;
- case LBRA:
- tlp->se.m[inst->subid].sp = s;
- continue;
- case RBRA:
- tlp->se.m[inst->subid].ep = s;
- continue;
- case ANY:
- if(r != '\n')
- if(_renewthread(nl, inst->next, ms, &tlp->se)==nle)
- return -1;
- break;
- case ANYNL:
- if(_renewthread(nl, inst->next, ms, &tlp->se)==nle)
- return -1;
- break;
- case BOL:
- if(s == bol || *(s-1) == '\n')
- continue;
- break;
- case EOL:
- if(s == j->eol || r == 0 || r == '\n')
- continue;
- break;
- case CCLASS:
- ep = inst->cp->end;
- for(rp = inst->cp->spans; rp < ep; rp += 2)
- if(r >= rp[0] && r <= rp[1]){
- if(_renewthread(nl, inst->next, ms, &tlp->se)==nle)
- return -1;
- break;
- }
- break;
- case NCCLASS:
- ep = inst->cp->end;
- for(rp = inst->cp->spans; rp < ep; rp += 2)
- if(r >= rp[0] && r <= rp[1])
- break;
- if(rp == ep)
- if(_renewthread(nl, inst->next, ms, &tlp->se)==nle)
- return -1;
- break;
- case OR:
- /* evaluate right choice later */
- if(_renewthread(tlp, inst->right, ms, &tlp->se) == tle)
- return -1;
- /* efficiency: advance and re-evaluate */
- continue;
- case END: /* Match! */
- match = 1;
- tlp->se.m[0].ep = s;
- if(mp != 0)
- _renewmatch(mp, ms, &tlp->se);
- break;
+ for(r = L'☺'; r != L'\0'; sp += i) {
+ i = chartorune(&r, sp);
+ 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;
+ }
+ t = clist->head;
+ if(t == nil)
+ break;
+ ci = t->i;
+Again:
+ if(ci->gen == gen)
+ goto Done;
+ ci->gen = gen;
+ switch(ci->op) {
+ case ORUNE:
+ if(r != ci->r)
+ goto Done;
+ case OANY: /* fallthrough */
+ next = t->next;
+ t->i = ci + 1;
+ t->next = nil;
+ *nlist->tail = t;
+ nlist->tail = &t->next;
+ goto Next;
+ case OCLASS:
+ Class:
+ if(r < ci->r)
+ goto Done;
+ if(r > ci->r1) {
+ ci++;
+ goto Class;
+ }
+ next = t->next;
+ t->i = ci->a;
+ t->next = nil;
+ *nlist->tail = t;
+ nlist->tail = &t->next;
+ goto Next;
+ case ONOTNL:
+ if(r != L'\n') {
+ ci++;
+ goto Again;
+ }
+ goto Done;
+ case OBOL:
+ if(sp == str || sp[-1] == '\n') {
+ ci++;
+ goto Again;
+ }
+ goto Done;
+ case OEOL:
+ if(r == L'\n' || r == L'\0' && ep == nil) {
+ ci++;
+ goto Again;
+ }
+ goto Done;
+ case OJMP:
+ ci = ci->a;
+ goto Again;
+ case OSPLIT:
+ if(avail == nil) {
+ assert(pool < p->threads + p->nthr);
+ next = pool++;
+ } else {
+ next = avail;
+ avail = avail->next;
+ }
+ next->i = ci->b;
+ if(msize > 0)
+ memcpy(next->sem, t->sem, sizeof(Resub)*msize);
+ next->next = t->next;
+ next->gen = t->gen;
+ t->next = next;
+ ci = ci->a;
+ goto Again;
+ case OSAVE:
+ if(ci->sub < msize)
+ t->sem[ci->sub].sp = sp;
+ ci++;
+ goto Again;
+ case OUNSAVE:
+ if(ci->sub == 0) {
+ matchgen = t->gen;
+ if(sem != nil && msize > 0) {
+ memcpy(sem, t->sem, sizeof(Resub)*msize);
+ sem->ep = sp;