13e12c5d1SDavid du Colombier #include "sam.h"
23e12c5d1SDavid du Colombier
33e12c5d1SDavid du Colombier Rangeset sel;
43e12c5d1SDavid du Colombier String lastregexp;
53e12c5d1SDavid du Colombier /*
63e12c5d1SDavid du Colombier * Machine Information
73e12c5d1SDavid du Colombier */
83e12c5d1SDavid du Colombier typedef struct Inst Inst;
93e12c5d1SDavid du Colombier
103e12c5d1SDavid du Colombier struct Inst
113e12c5d1SDavid du Colombier {
12*82726826SDavid du Colombier long type; /* <= Runemax ==> literal, otherwise action */
133e12c5d1SDavid du Colombier union {
143e12c5d1SDavid du Colombier int rsid;
153e12c5d1SDavid du Colombier int rsubid;
163e12c5d1SDavid du Colombier int class;
173e12c5d1SDavid du Colombier struct Inst *rother;
183e12c5d1SDavid du Colombier struct Inst *rright;
193e12c5d1SDavid du Colombier } r;
203e12c5d1SDavid du Colombier union{
213e12c5d1SDavid du Colombier struct Inst *lleft;
223e12c5d1SDavid du Colombier struct Inst *lnext;
233e12c5d1SDavid du Colombier } l;
243e12c5d1SDavid du Colombier };
253e12c5d1SDavid du Colombier #define sid r.rsid
263e12c5d1SDavid du Colombier #define subid r.rsubid
273e12c5d1SDavid du Colombier #define rclass r.class
283e12c5d1SDavid du Colombier #define other r.rother
293e12c5d1SDavid du Colombier #define right r.rright
303e12c5d1SDavid du Colombier #define left l.lleft
313e12c5d1SDavid du Colombier #define next l.lnext
323e12c5d1SDavid du Colombier
333e12c5d1SDavid du Colombier #define NPROG 1024
343e12c5d1SDavid du Colombier Inst program[NPROG];
353e12c5d1SDavid du Colombier Inst *progp;
363e12c5d1SDavid du Colombier Inst *startinst; /* First inst. of program; might not be program[0] */
373e12c5d1SDavid du Colombier Inst *bstartinst; /* same for backwards machine */
383e12c5d1SDavid du Colombier
393e12c5d1SDavid du Colombier typedef struct Ilist Ilist;
403e12c5d1SDavid du Colombier struct Ilist
413e12c5d1SDavid du Colombier {
423e12c5d1SDavid du Colombier Inst *inst; /* Instruction of the thread */
433e12c5d1SDavid du Colombier Rangeset se;
443e12c5d1SDavid du Colombier Posn startp; /* first char of match */
453e12c5d1SDavid du Colombier };
463e12c5d1SDavid du Colombier
47e6dcbf51SDavid du Colombier #define NLIST 127
483e12c5d1SDavid du Colombier
493e12c5d1SDavid du Colombier Ilist *tl, *nl; /* This list, next list */
50e6dcbf51SDavid du Colombier Ilist list[2][NLIST+1]; /* +1 for trailing null */
513e12c5d1SDavid du Colombier static Rangeset sempty;
523e12c5d1SDavid du Colombier
533e12c5d1SDavid du Colombier /*
543e12c5d1SDavid du Colombier * Actions and Tokens
553e12c5d1SDavid du Colombier *
563e12c5d1SDavid du Colombier * 0x100xx are operators, value == precedence
573e12c5d1SDavid du Colombier * 0x200xx are tokens, i.e. operands for operators
583e12c5d1SDavid du Colombier */
59*82726826SDavid du Colombier enum {
60*82726826SDavid du Colombier OPERATOR = Runemask+1, /* Bitmask of all operators */
61*82726826SDavid du Colombier START = OPERATOR, /* Start, used for marker on stack */
62*82726826SDavid du Colombier RBRA, /* Right bracket, ) */
63*82726826SDavid du Colombier LBRA, /* Left bracket, ( */
64*82726826SDavid du Colombier OR, /* Alternation, | */
65*82726826SDavid du Colombier CAT, /* Concatentation, implicit operator */
66*82726826SDavid du Colombier STAR, /* Closure, * */
67*82726826SDavid du Colombier PLUS, /* a+ == aa* */
68*82726826SDavid du Colombier QUEST, /* a? == a|nothing, i.e. 0 or 1 a's */
693e12c5d1SDavid du Colombier
70*82726826SDavid du Colombier ANY = OPERATOR<<1, /* Any character but newline, . */
71*82726826SDavid du Colombier NOP, /* No operation, internal use only */
72*82726826SDavid du Colombier BOL, /* Beginning of line, ^ */
73*82726826SDavid du Colombier EOL, /* End of line, $ */
74*82726826SDavid du Colombier CCLASS, /* Character class, [] */
75*82726826SDavid du Colombier NCCLASS, /* Negated character class, [^] */
76*82726826SDavid du Colombier END, /* Terminate: match found */
77*82726826SDavid du Colombier
78*82726826SDavid du Colombier ISATOR = OPERATOR,
79*82726826SDavid du Colombier ISAND = OPERATOR<<1,
80*82726826SDavid du Colombier };
813e12c5d1SDavid du Colombier
823e12c5d1SDavid du Colombier /*
833e12c5d1SDavid du Colombier * Parser Information
843e12c5d1SDavid du Colombier */
853e12c5d1SDavid du Colombier typedef struct Node Node;
863e12c5d1SDavid du Colombier struct Node
873e12c5d1SDavid du Colombier {
883e12c5d1SDavid du Colombier Inst *first;
893e12c5d1SDavid du Colombier Inst *last;
903e12c5d1SDavid du Colombier };
913e12c5d1SDavid du Colombier
923e12c5d1SDavid du Colombier #define NSTACK 20
933e12c5d1SDavid du Colombier Node andstack[NSTACK];
943e12c5d1SDavid du Colombier Node *andp;
953e12c5d1SDavid du Colombier int atorstack[NSTACK];
963e12c5d1SDavid du Colombier int *atorp;
973e12c5d1SDavid du Colombier int lastwasand; /* Last token was operand */
983e12c5d1SDavid du Colombier int cursubid;
993e12c5d1SDavid du Colombier int subidstack[NSTACK];
1003e12c5d1SDavid du Colombier int *subidp;
1013e12c5d1SDavid du Colombier int backwards;
1023e12c5d1SDavid du Colombier int nbra;
1033e12c5d1SDavid du Colombier Rune *exprp; /* pointer to next character in source expression */
1043e12c5d1SDavid du Colombier #define DCLASS 10 /* allocation increment */
1053e12c5d1SDavid du Colombier int nclass; /* number active */
1063e12c5d1SDavid du Colombier int Nclass; /* high water mark */
1073e12c5d1SDavid du Colombier Rune **class;
1083e12c5d1SDavid du Colombier int negateclass;
1093e12c5d1SDavid du Colombier
110e6dcbf51SDavid du Colombier int addinst(Ilist *l, Inst *inst, Rangeset *sep);
1113e12c5d1SDavid du Colombier void newmatch(Rangeset*);
1123e12c5d1SDavid du Colombier void bnewmatch(Rangeset*);
1133e12c5d1SDavid du Colombier void pushand(Inst*, Inst*);
1143e12c5d1SDavid du Colombier void pushator(int);
1153e12c5d1SDavid du Colombier Node *popand(int);
1163e12c5d1SDavid du Colombier int popator(void);
1173e12c5d1SDavid du Colombier void startlex(Rune*);
1183e12c5d1SDavid du Colombier int lex(void);
1193e12c5d1SDavid du Colombier void operator(int);
1203e12c5d1SDavid du Colombier void operand(int);
1213e12c5d1SDavid du Colombier void evaluntil(int);
1223e12c5d1SDavid du Colombier void optimize(Inst*);
1233e12c5d1SDavid du Colombier void bldcclass(void);
1243e12c5d1SDavid du Colombier
1253e12c5d1SDavid du Colombier void
regerror(Err e)1263e12c5d1SDavid du Colombier regerror(Err e)
1273e12c5d1SDavid du Colombier {
1283e12c5d1SDavid du Colombier Strzero(&lastregexp);
1293e12c5d1SDavid du Colombier error(e);
1303e12c5d1SDavid du Colombier }
1313e12c5d1SDavid du Colombier
1323e12c5d1SDavid du Colombier void
regerror_c(Err e,int c)1333e12c5d1SDavid du Colombier regerror_c(Err e, int c)
1343e12c5d1SDavid du Colombier {
1353e12c5d1SDavid du Colombier Strzero(&lastregexp);
1363e12c5d1SDavid du Colombier error_c(e, c);
1373e12c5d1SDavid du Colombier }
1383e12c5d1SDavid du Colombier
1393e12c5d1SDavid du Colombier Inst *
newinst(int t)1403e12c5d1SDavid du Colombier newinst(int t)
1413e12c5d1SDavid du Colombier {
1423e12c5d1SDavid du Colombier if(progp >= &program[NPROG])
1433e12c5d1SDavid du Colombier regerror(Etoolong);
1443e12c5d1SDavid du Colombier progp->type = t;
1453e12c5d1SDavid du Colombier progp->left = 0;
1463e12c5d1SDavid du Colombier progp->right = 0;
1473e12c5d1SDavid du Colombier return progp++;
1483e12c5d1SDavid du Colombier }
1493e12c5d1SDavid du Colombier
1503e12c5d1SDavid du Colombier Inst *
realcompile(Rune * s)1513e12c5d1SDavid du Colombier realcompile(Rune *s)
1523e12c5d1SDavid du Colombier {
1533e12c5d1SDavid du Colombier int token;
1543e12c5d1SDavid du Colombier
1553e12c5d1SDavid du Colombier startlex(s);
1563e12c5d1SDavid du Colombier atorp = atorstack;
1573e12c5d1SDavid du Colombier andp = andstack;
1583e12c5d1SDavid du Colombier subidp = subidstack;
1593e12c5d1SDavid du Colombier cursubid = 0;
1603e12c5d1SDavid du Colombier lastwasand = FALSE;
1613e12c5d1SDavid du Colombier /* Start with a low priority operator to prime parser */
1623e12c5d1SDavid du Colombier pushator(START-1);
1633e12c5d1SDavid du Colombier while((token=lex()) != END){
1643e12c5d1SDavid du Colombier if((token&ISATOR) == OPERATOR)
1653e12c5d1SDavid du Colombier operator(token);
1663e12c5d1SDavid du Colombier else
1673e12c5d1SDavid du Colombier operand(token);
1683e12c5d1SDavid du Colombier }
1693e12c5d1SDavid du Colombier /* Close with a low priority operator */
1703e12c5d1SDavid du Colombier evaluntil(START);
1713e12c5d1SDavid du Colombier /* Force END */
1723e12c5d1SDavid du Colombier operand(END);
1733e12c5d1SDavid du Colombier evaluntil(START);
1743e12c5d1SDavid du Colombier if(nbra)
1753e12c5d1SDavid du Colombier regerror(Eleftpar);
1763e12c5d1SDavid du Colombier --andp; /* points to first and only operand */
1773e12c5d1SDavid du Colombier return andp->first;
1783e12c5d1SDavid du Colombier }
1793e12c5d1SDavid du Colombier
1803e12c5d1SDavid du Colombier void
compile(String * s)1813e12c5d1SDavid du Colombier compile(String *s)
1823e12c5d1SDavid du Colombier {
1833e12c5d1SDavid du Colombier int i;
1843e12c5d1SDavid du Colombier Inst *oprogp;
1853e12c5d1SDavid du Colombier
1863e12c5d1SDavid du Colombier if(Strcmp(s, &lastregexp)==0)
1873e12c5d1SDavid du Colombier return;
1883e12c5d1SDavid du Colombier for(i=0; i<nclass; i++)
1893e12c5d1SDavid du Colombier free(class[i]);
1903e12c5d1SDavid du Colombier nclass = 0;
1913e12c5d1SDavid du Colombier progp = program;
1923e12c5d1SDavid du Colombier backwards = FALSE;
1933e12c5d1SDavid du Colombier startinst = realcompile(s->s);
1943e12c5d1SDavid du Colombier optimize(program);
1953e12c5d1SDavid du Colombier oprogp = progp;
1963e12c5d1SDavid du Colombier backwards = TRUE;
1973e12c5d1SDavid du Colombier bstartinst = realcompile(s->s);
1983e12c5d1SDavid du Colombier optimize(oprogp);
1993e12c5d1SDavid du Colombier Strduplstr(&lastregexp, s);
2003e12c5d1SDavid du Colombier }
2013e12c5d1SDavid du Colombier
2023e12c5d1SDavid du Colombier void
operand(int t)2033e12c5d1SDavid du Colombier operand(int t)
2043e12c5d1SDavid du Colombier {
2053e12c5d1SDavid du Colombier Inst *i;
2063e12c5d1SDavid du Colombier if(lastwasand)
2073e12c5d1SDavid du Colombier operator(CAT); /* catenate is implicit */
2083e12c5d1SDavid du Colombier i = newinst(t);
2093e12c5d1SDavid du Colombier if(t == CCLASS){
2103e12c5d1SDavid du Colombier if(negateclass)
2113e12c5d1SDavid du Colombier i->type = NCCLASS; /* UGH */
2123e12c5d1SDavid du Colombier i->rclass = nclass-1; /* UGH */
2133e12c5d1SDavid du Colombier }
2143e12c5d1SDavid du Colombier pushand(i, i);
2153e12c5d1SDavid du Colombier lastwasand = TRUE;
2163e12c5d1SDavid du Colombier }
2173e12c5d1SDavid du Colombier
2183e12c5d1SDavid du Colombier void
operator(int t)2193e12c5d1SDavid du Colombier operator(int t)
2203e12c5d1SDavid du Colombier {
2213e12c5d1SDavid du Colombier if(t==RBRA && --nbra<0)
2223e12c5d1SDavid du Colombier regerror(Erightpar);
2233e12c5d1SDavid du Colombier if(t==LBRA){
2243e12c5d1SDavid du Colombier /*
2253e12c5d1SDavid du Colombier * if(++cursubid >= NSUBEXP)
2263e12c5d1SDavid du Colombier * regerror(Esubexp);
2273e12c5d1SDavid du Colombier */
2283e12c5d1SDavid du Colombier cursubid++; /* silently ignored */
2293e12c5d1SDavid du Colombier nbra++;
2303e12c5d1SDavid du Colombier if(lastwasand)
2313e12c5d1SDavid du Colombier operator(CAT);
2323e12c5d1SDavid du Colombier }else
2333e12c5d1SDavid du Colombier evaluntil(t);
2343e12c5d1SDavid du Colombier if(t!=RBRA)
2353e12c5d1SDavid du Colombier pushator(t);
2363e12c5d1SDavid du Colombier lastwasand = FALSE;
2373e12c5d1SDavid du Colombier if(t==STAR || t==QUEST || t==PLUS || t==RBRA)
2383e12c5d1SDavid du Colombier lastwasand = TRUE; /* these look like operands */
2393e12c5d1SDavid du Colombier }
2403e12c5d1SDavid du Colombier
2413e12c5d1SDavid du Colombier void
cant(char * s)2423e12c5d1SDavid du Colombier cant(char *s)
2433e12c5d1SDavid du Colombier {
2443e12c5d1SDavid du Colombier char buf[100];
2453e12c5d1SDavid du Colombier
2463e12c5d1SDavid du Colombier sprint(buf, "regexp: can't happen: %s", s);
2473e12c5d1SDavid du Colombier panic(buf);
2483e12c5d1SDavid du Colombier }
2493e12c5d1SDavid du Colombier
2503e12c5d1SDavid du Colombier void
pushand(Inst * f,Inst * l)2513e12c5d1SDavid du Colombier pushand(Inst *f, Inst *l)
2523e12c5d1SDavid du Colombier {
2533e12c5d1SDavid du Colombier if(andp >= &andstack[NSTACK])
2543e12c5d1SDavid du Colombier cant("operand stack overflow");
2553e12c5d1SDavid du Colombier andp->first = f;
2563e12c5d1SDavid du Colombier andp->last = l;
2573e12c5d1SDavid du Colombier andp++;
2583e12c5d1SDavid du Colombier }
2593e12c5d1SDavid du Colombier
2603e12c5d1SDavid du Colombier void
pushator(int t)2613e12c5d1SDavid du Colombier pushator(int t)
2623e12c5d1SDavid du Colombier {
2633e12c5d1SDavid du Colombier if(atorp >= &atorstack[NSTACK])
2643e12c5d1SDavid du Colombier cant("operator stack overflow");
2653e12c5d1SDavid du Colombier *atorp++=t;
2663e12c5d1SDavid du Colombier if(cursubid >= NSUBEXP)
2673e12c5d1SDavid du Colombier *subidp++= -1;
2683e12c5d1SDavid du Colombier else
2693e12c5d1SDavid du Colombier *subidp++=cursubid;
2703e12c5d1SDavid du Colombier }
2713e12c5d1SDavid du Colombier
2723e12c5d1SDavid du Colombier Node *
popand(int op)2733e12c5d1SDavid du Colombier popand(int op)
2743e12c5d1SDavid du Colombier {
2753e12c5d1SDavid du Colombier if(andp <= &andstack[0])
2763e12c5d1SDavid du Colombier if(op)
2773e12c5d1SDavid du Colombier regerror_c(Emissop, op);
2783e12c5d1SDavid du Colombier else
2793e12c5d1SDavid du Colombier regerror(Ebadregexp);
2803e12c5d1SDavid du Colombier return --andp;
2813e12c5d1SDavid du Colombier }
2823e12c5d1SDavid du Colombier
2833e12c5d1SDavid du Colombier int
popator(void)2843e12c5d1SDavid du Colombier popator(void)
2853e12c5d1SDavid du Colombier {
2863e12c5d1SDavid du Colombier if(atorp <= &atorstack[0])
2873e12c5d1SDavid du Colombier cant("operator stack underflow");
2883e12c5d1SDavid du Colombier --subidp;
2893e12c5d1SDavid du Colombier return *--atorp;
2903e12c5d1SDavid du Colombier }
2913e12c5d1SDavid du Colombier
2923e12c5d1SDavid du Colombier void
evaluntil(int pri)2933e12c5d1SDavid du Colombier evaluntil(int pri)
2943e12c5d1SDavid du Colombier {
2953e12c5d1SDavid du Colombier Node *op1, *op2, *t;
2963e12c5d1SDavid du Colombier Inst *inst1, *inst2;
2973e12c5d1SDavid du Colombier
2983e12c5d1SDavid du Colombier while(pri==RBRA || atorp[-1]>=pri){
2993e12c5d1SDavid du Colombier switch(popator()){
3003e12c5d1SDavid du Colombier case LBRA:
3013e12c5d1SDavid du Colombier op1 = popand('(');
3023e12c5d1SDavid du Colombier inst2 = newinst(RBRA);
3033e12c5d1SDavid du Colombier inst2->subid = *subidp;
3043e12c5d1SDavid du Colombier op1->last->next = inst2;
3053e12c5d1SDavid du Colombier inst1 = newinst(LBRA);
3063e12c5d1SDavid du Colombier inst1->subid = *subidp;
3073e12c5d1SDavid du Colombier inst1->next = op1->first;
3083e12c5d1SDavid du Colombier pushand(inst1, inst2);
3093e12c5d1SDavid du Colombier return; /* must have been RBRA */
3103e12c5d1SDavid du Colombier default:
3113e12c5d1SDavid du Colombier panic("unknown regexp operator");
3123e12c5d1SDavid du Colombier break;
3133e12c5d1SDavid du Colombier case OR:
3143e12c5d1SDavid du Colombier op2 = popand('|');
3153e12c5d1SDavid du Colombier op1 = popand('|');
3163e12c5d1SDavid du Colombier inst2 = newinst(NOP);
3173e12c5d1SDavid du Colombier op2->last->next = inst2;
3183e12c5d1SDavid du Colombier op1->last->next = inst2;
3193e12c5d1SDavid du Colombier inst1 = newinst(OR);
3203e12c5d1SDavid du Colombier inst1->right = op1->first;
3213e12c5d1SDavid du Colombier inst1->left = op2->first;
3223e12c5d1SDavid du Colombier pushand(inst1, inst2);
3233e12c5d1SDavid du Colombier break;
3243e12c5d1SDavid du Colombier case CAT:
3253e12c5d1SDavid du Colombier op2 = popand(0);
3263e12c5d1SDavid du Colombier op1 = popand(0);
3273e12c5d1SDavid du Colombier if(backwards && op2->first->type!=END)
3283e12c5d1SDavid du Colombier t = op1, op1 = op2, op2 = t;
3293e12c5d1SDavid du Colombier op1->last->next = op2->first;
3303e12c5d1SDavid du Colombier pushand(op1->first, op2->last);
3313e12c5d1SDavid du Colombier break;
3323e12c5d1SDavid du Colombier case STAR:
3333e12c5d1SDavid du Colombier op2 = popand('*');
3343e12c5d1SDavid du Colombier inst1 = newinst(OR);
3353e12c5d1SDavid du Colombier op2->last->next = inst1;
3363e12c5d1SDavid du Colombier inst1->right = op2->first;
3373e12c5d1SDavid du Colombier pushand(inst1, inst1);
3383e12c5d1SDavid du Colombier break;
3393e12c5d1SDavid du Colombier case PLUS:
3403e12c5d1SDavid du Colombier op2 = popand('+');
3413e12c5d1SDavid du Colombier inst1 = newinst(OR);
3423e12c5d1SDavid du Colombier op2->last->next = inst1;
3433e12c5d1SDavid du Colombier inst1->right = op2->first;
3443e12c5d1SDavid du Colombier pushand(op2->first, inst1);
3453e12c5d1SDavid du Colombier break;
3463e12c5d1SDavid du Colombier case QUEST:
3473e12c5d1SDavid du Colombier op2 = popand('?');
3483e12c5d1SDavid du Colombier inst1 = newinst(OR);
3493e12c5d1SDavid du Colombier inst2 = newinst(NOP);
3503e12c5d1SDavid du Colombier inst1->left = inst2;
3513e12c5d1SDavid du Colombier inst1->right = op2->first;
3523e12c5d1SDavid du Colombier op2->last->next = inst2;
3533e12c5d1SDavid du Colombier pushand(inst1, inst2);
3543e12c5d1SDavid du Colombier break;
3553e12c5d1SDavid du Colombier }
3563e12c5d1SDavid du Colombier }
3573e12c5d1SDavid du Colombier }
3583e12c5d1SDavid du Colombier
3593e12c5d1SDavid du Colombier
3603e12c5d1SDavid du Colombier void
optimize(Inst * start)3613e12c5d1SDavid du Colombier optimize(Inst *start)
3623e12c5d1SDavid du Colombier {
3633e12c5d1SDavid du Colombier Inst *inst, *target;
3643e12c5d1SDavid du Colombier
3653e12c5d1SDavid du Colombier for(inst=start; inst->type!=END; inst++){
3663e12c5d1SDavid du Colombier target = inst->next;
3673e12c5d1SDavid du Colombier while(target->type == NOP)
3683e12c5d1SDavid du Colombier target = target->next;
3693e12c5d1SDavid du Colombier inst->next = target;
3703e12c5d1SDavid du Colombier }
3713e12c5d1SDavid du Colombier }
3723e12c5d1SDavid du Colombier
3733e12c5d1SDavid du Colombier #ifdef DEBUG
3743e12c5d1SDavid du Colombier void
dumpstack(void)3753e12c5d1SDavid du Colombier dumpstack(void){
3763e12c5d1SDavid du Colombier Node *stk;
3773e12c5d1SDavid du Colombier int *ip;
3783e12c5d1SDavid du Colombier
3793e12c5d1SDavid du Colombier dprint("operators\n");
3803e12c5d1SDavid du Colombier for(ip = atorstack; ip<atorp; ip++)
3813e12c5d1SDavid du Colombier dprint("0%o\n", *ip);
3823e12c5d1SDavid du Colombier dprint("operands\n");
3833e12c5d1SDavid du Colombier for(stk = andstack; stk<andp; stk++)
3843e12c5d1SDavid du Colombier dprint("0%o\t0%o\n", stk->first->type, stk->last->type);
3853e12c5d1SDavid du Colombier }
3863e12c5d1SDavid du Colombier void
dump(void)3873e12c5d1SDavid du Colombier dump(void){
3883e12c5d1SDavid du Colombier Inst *l;
3893e12c5d1SDavid du Colombier
3903e12c5d1SDavid du Colombier l = program;
3913e12c5d1SDavid du Colombier do{
3923e12c5d1SDavid du Colombier dprint("%d:\t0%o\t%d\t%d\n", l-program, l->type,
3933e12c5d1SDavid du Colombier l->left-program, l->right-program);
3943e12c5d1SDavid du Colombier }while(l++->type);
3953e12c5d1SDavid du Colombier }
3963e12c5d1SDavid du Colombier #endif
3973e12c5d1SDavid du Colombier
3983e12c5d1SDavid du Colombier void
startlex(Rune * s)3993e12c5d1SDavid du Colombier startlex(Rune *s)
4003e12c5d1SDavid du Colombier {
4013e12c5d1SDavid du Colombier exprp = s;
4023e12c5d1SDavid du Colombier nbra = 0;
4033e12c5d1SDavid du Colombier }
4043e12c5d1SDavid du Colombier
4053e12c5d1SDavid du Colombier
4063e12c5d1SDavid du Colombier int
lex(void)4073e12c5d1SDavid du Colombier lex(void){
4083e12c5d1SDavid du Colombier int c= *exprp++;
4093e12c5d1SDavid du Colombier
4103e12c5d1SDavid du Colombier switch(c){
4113e12c5d1SDavid du Colombier case '\\':
4123e12c5d1SDavid du Colombier if(*exprp)
4133e12c5d1SDavid du Colombier if((c= *exprp++)=='n')
4143e12c5d1SDavid du Colombier c='\n';
4153e12c5d1SDavid du Colombier break;
4163e12c5d1SDavid du Colombier case 0:
4173e12c5d1SDavid du Colombier c = END;
4183e12c5d1SDavid du Colombier --exprp; /* In case we come here again */
4193e12c5d1SDavid du Colombier break;
4203e12c5d1SDavid du Colombier case '*':
4213e12c5d1SDavid du Colombier c = STAR;
4223e12c5d1SDavid du Colombier break;
4233e12c5d1SDavid du Colombier case '?':
4243e12c5d1SDavid du Colombier c = QUEST;
4253e12c5d1SDavid du Colombier break;
4263e12c5d1SDavid du Colombier case '+':
4273e12c5d1SDavid du Colombier c = PLUS;
4283e12c5d1SDavid du Colombier break;
4293e12c5d1SDavid du Colombier case '|':
4303e12c5d1SDavid du Colombier c = OR;
4313e12c5d1SDavid du Colombier break;
4323e12c5d1SDavid du Colombier case '.':
4333e12c5d1SDavid du Colombier c = ANY;
4343e12c5d1SDavid du Colombier break;
4353e12c5d1SDavid du Colombier case '(':
4363e12c5d1SDavid du Colombier c = LBRA;
4373e12c5d1SDavid du Colombier break;
4383e12c5d1SDavid du Colombier case ')':
4393e12c5d1SDavid du Colombier c = RBRA;
4403e12c5d1SDavid du Colombier break;
4413e12c5d1SDavid du Colombier case '^':
4423e12c5d1SDavid du Colombier c = BOL;
4433e12c5d1SDavid du Colombier break;
4443e12c5d1SDavid du Colombier case '$':
4453e12c5d1SDavid du Colombier c = EOL;
4463e12c5d1SDavid du Colombier break;
4473e12c5d1SDavid du Colombier case '[':
4483e12c5d1SDavid du Colombier c = CCLASS;
4493e12c5d1SDavid du Colombier bldcclass();
4503e12c5d1SDavid du Colombier break;
4513e12c5d1SDavid du Colombier }
4523e12c5d1SDavid du Colombier return c;
4533e12c5d1SDavid du Colombier }
4543e12c5d1SDavid du Colombier
4553e12c5d1SDavid du Colombier long
nextrec(void)4563e12c5d1SDavid du Colombier nextrec(void){
4573e12c5d1SDavid du Colombier if(exprp[0]==0 || (exprp[0]=='\\' && exprp[1]==0))
4583e12c5d1SDavid du Colombier regerror(Ebadclass);
4593e12c5d1SDavid du Colombier if(exprp[0] == '\\'){
4603e12c5d1SDavid du Colombier exprp++;
4613e12c5d1SDavid du Colombier if(*exprp=='n'){
4623e12c5d1SDavid du Colombier exprp++;
4633e12c5d1SDavid du Colombier return '\n';
4643e12c5d1SDavid du Colombier }
465*82726826SDavid du Colombier return *exprp++|(Runemax+1);
4663e12c5d1SDavid du Colombier }
4673e12c5d1SDavid du Colombier return *exprp++;
4683e12c5d1SDavid du Colombier }
4693e12c5d1SDavid du Colombier
4703e12c5d1SDavid du Colombier void
bldcclass(void)4713e12c5d1SDavid du Colombier bldcclass(void)
4723e12c5d1SDavid du Colombier {
4733e12c5d1SDavid du Colombier long c1, c2, n, na;
4743e12c5d1SDavid du Colombier Rune *classp;
4753e12c5d1SDavid du Colombier
4763e12c5d1SDavid du Colombier classp = emalloc(DCLASS*RUNESIZE);
4773e12c5d1SDavid du Colombier n = 0;
4783e12c5d1SDavid du Colombier na = DCLASS;
4793e12c5d1SDavid du Colombier /* we have already seen the '[' */
4803e12c5d1SDavid du Colombier if(*exprp == '^'){
4813e12c5d1SDavid du Colombier classp[n++] = '\n'; /* don't match newline in negate case */
4823e12c5d1SDavid du Colombier negateclass = TRUE;
4833e12c5d1SDavid du Colombier exprp++;
4843e12c5d1SDavid du Colombier }else
4853e12c5d1SDavid du Colombier negateclass = FALSE;
4863e12c5d1SDavid du Colombier while((c1 = nextrec()) != ']'){
4873e12c5d1SDavid du Colombier if(c1 == '-'){
4883e12c5d1SDavid du Colombier Error:
4893e12c5d1SDavid du Colombier free(classp);
4903e12c5d1SDavid du Colombier regerror(Ebadclass);
4913e12c5d1SDavid du Colombier }
4923e12c5d1SDavid du Colombier if(n+4 >= na){ /* 3 runes plus NUL */
4933e12c5d1SDavid du Colombier na += DCLASS;
4943e12c5d1SDavid du Colombier classp = erealloc(classp, na*RUNESIZE);
4953e12c5d1SDavid du Colombier }
4963e12c5d1SDavid du Colombier if(*exprp == '-'){
4973e12c5d1SDavid du Colombier exprp++; /* eat '-' */
4983e12c5d1SDavid du Colombier if((c2 = nextrec()) == ']')
4993e12c5d1SDavid du Colombier goto Error;
500*82726826SDavid du Colombier classp[n+0] = Runemax;
5013e12c5d1SDavid du Colombier classp[n+1] = c1;
5023e12c5d1SDavid du Colombier classp[n+2] = c2;
5033e12c5d1SDavid du Colombier n += 3;
5043e12c5d1SDavid du Colombier }else
5053e12c5d1SDavid du Colombier classp[n++] = c1;
5063e12c5d1SDavid du Colombier }
5073e12c5d1SDavid du Colombier classp[n] = 0;
5083e12c5d1SDavid du Colombier if(nclass == Nclass){
5093e12c5d1SDavid du Colombier Nclass += DCLASS;
5103e12c5d1SDavid du Colombier class = erealloc(class, Nclass*sizeof(Rune*));
5113e12c5d1SDavid du Colombier }
5123e12c5d1SDavid du Colombier class[nclass++] = classp;
5133e12c5d1SDavid du Colombier }
5143e12c5d1SDavid du Colombier
5153e12c5d1SDavid du Colombier int
classmatch(int classno,int c,int negate)5163e12c5d1SDavid du Colombier classmatch(int classno, int c, int negate)
5173e12c5d1SDavid du Colombier {
5183e12c5d1SDavid du Colombier Rune *p;
5193e12c5d1SDavid du Colombier
5203e12c5d1SDavid du Colombier p = class[classno];
5213e12c5d1SDavid du Colombier while(*p){
522*82726826SDavid du Colombier if(*p == Runemax){
5233e12c5d1SDavid du Colombier if(p[1]<=c && c<=p[2])
5243e12c5d1SDavid du Colombier return !negate;
5253e12c5d1SDavid du Colombier p += 3;
5263e12c5d1SDavid du Colombier }else if(*p++ == c)
5273e12c5d1SDavid du Colombier return !negate;
5283e12c5d1SDavid du Colombier }
5293e12c5d1SDavid du Colombier return negate;
5303e12c5d1SDavid du Colombier }
5313e12c5d1SDavid du Colombier
5323e12c5d1SDavid du Colombier /*
5333e12c5d1SDavid du Colombier * Note optimization in addinst:
5343e12c5d1SDavid du Colombier * *l must be pending when addinst called; if *l has been looked
5353e12c5d1SDavid du Colombier * at already, the optimization is a bug.
5363e12c5d1SDavid du Colombier */
537e6dcbf51SDavid du Colombier int
addinst(Ilist * l,Inst * inst,Rangeset * sep)5383e12c5d1SDavid du Colombier addinst(Ilist *l, Inst *inst, Rangeset *sep)
5393e12c5d1SDavid du Colombier {
5403e12c5d1SDavid du Colombier Ilist *p;
5413e12c5d1SDavid du Colombier
5423e12c5d1SDavid du Colombier for(p = l; p->inst; p++){
5433e12c5d1SDavid du Colombier if(p->inst==inst){
5443e12c5d1SDavid du Colombier if((sep)->p[0].p1 < p->se.p[0].p1)
5453e12c5d1SDavid du Colombier p->se= *sep; /* this would be bug */
546e6dcbf51SDavid du Colombier return 0; /* It's already there */
5473e12c5d1SDavid du Colombier }
5483e12c5d1SDavid du Colombier }
5493e12c5d1SDavid du Colombier p->inst = inst;
5503e12c5d1SDavid du Colombier p->se= *sep;
5513e12c5d1SDavid du Colombier (p+1)->inst = 0;
552e6dcbf51SDavid du Colombier return 1;
5533e12c5d1SDavid du Colombier }
5543e12c5d1SDavid du Colombier
5553e12c5d1SDavid du Colombier int
execute(File * f,Posn startp,Posn eof)5563e12c5d1SDavid du Colombier execute(File *f, Posn startp, Posn eof)
5573e12c5d1SDavid du Colombier {
5583e12c5d1SDavid du Colombier int flag = 0;
5593e12c5d1SDavid du Colombier Inst *inst;
5603e12c5d1SDavid du Colombier Ilist *tlp;
5613e12c5d1SDavid du Colombier Posn p = startp;
5623e12c5d1SDavid du Colombier int nnl = 0, ntl;
5633e12c5d1SDavid du Colombier int c;
5643e12c5d1SDavid du Colombier int wrapped = 0;
5653e12c5d1SDavid du Colombier int startchar = startinst->type<OPERATOR? startinst->type : 0;
5663e12c5d1SDavid du Colombier
5673e12c5d1SDavid du Colombier list[0][0].inst = list[1][0].inst = 0;
5683e12c5d1SDavid du Colombier sel.p[0].p1 = -1;
5693e12c5d1SDavid du Colombier /* Execute machine once for each character */
5703e12c5d1SDavid du Colombier for(;;p++){
5713e12c5d1SDavid du Colombier doloop:
5727dd7cddfSDavid du Colombier c = filereadc(f, p);
5733e12c5d1SDavid du Colombier if(p>=eof || c<0){
5743e12c5d1SDavid du Colombier switch(wrapped++){
5753e12c5d1SDavid du Colombier case 0: /* let loop run one more click */
5763e12c5d1SDavid du Colombier case 2:
5773e12c5d1SDavid du Colombier break;
5783e12c5d1SDavid du Colombier case 1: /* expired; wrap to beginning */
5793e12c5d1SDavid du Colombier if(sel.p[0].p1>=0 || eof!=INFINITY)
5803e12c5d1SDavid du Colombier goto Return;
5813e12c5d1SDavid du Colombier list[0][0].inst = list[1][0].inst = 0;
5823e12c5d1SDavid du Colombier p = 0;
5833e12c5d1SDavid du Colombier goto doloop;
5843e12c5d1SDavid du Colombier default:
5853e12c5d1SDavid du Colombier goto Return;
5863e12c5d1SDavid du Colombier }
5873e12c5d1SDavid du Colombier }else if(((wrapped && p>=startp) || sel.p[0].p1>0) && nnl==0)
5883e12c5d1SDavid du Colombier break;
5893e12c5d1SDavid du Colombier /* fast check for first char */
5903e12c5d1SDavid du Colombier if(startchar && nnl==0 && c!=startchar)
5913e12c5d1SDavid du Colombier continue;
5923e12c5d1SDavid du Colombier tl = list[flag];
5933e12c5d1SDavid du Colombier nl = list[flag^=1];
5943e12c5d1SDavid du Colombier nl->inst = 0;
5953e12c5d1SDavid du Colombier ntl = nnl;
5963e12c5d1SDavid du Colombier nnl = 0;
5973e12c5d1SDavid du Colombier if(sel.p[0].p1<0 && (!wrapped || p<startp || startp==eof)){
5983e12c5d1SDavid du Colombier /* Add first instruction to this list */
599e6dcbf51SDavid du Colombier sempty.p[0].p1 = p;
600e6dcbf51SDavid du Colombier if(addinst(tl, startinst, &sempty))
6013e12c5d1SDavid du Colombier if(++ntl >= NLIST)
6023e12c5d1SDavid du Colombier Overflow:
6033e12c5d1SDavid du Colombier error(Eoverflow);
6043e12c5d1SDavid du Colombier }
6053e12c5d1SDavid du Colombier /* Execute machine until this list is empty */
6063e12c5d1SDavid du Colombier for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment = */
6073e12c5d1SDavid du Colombier Switchstmt:
6083e12c5d1SDavid du Colombier switch(inst->type){
6093e12c5d1SDavid du Colombier default: /* regular character */
6103e12c5d1SDavid du Colombier if(inst->type==c){
6113e12c5d1SDavid du Colombier Addinst:
612e6dcbf51SDavid du Colombier if(addinst(nl, inst->next, &tlp->se))
6133e12c5d1SDavid du Colombier if(++nnl >= NLIST)
6143e12c5d1SDavid du Colombier goto Overflow;
6153e12c5d1SDavid du Colombier }
6163e12c5d1SDavid du Colombier break;
6173e12c5d1SDavid du Colombier case LBRA:
6183e12c5d1SDavid du Colombier if(inst->subid>=0)
6193e12c5d1SDavid du Colombier tlp->se.p[inst->subid].p1 = p;
6203e12c5d1SDavid du Colombier inst = inst->next;
6213e12c5d1SDavid du Colombier goto Switchstmt;
6223e12c5d1SDavid du Colombier case RBRA:
6233e12c5d1SDavid du Colombier if(inst->subid>=0)
6243e12c5d1SDavid du Colombier tlp->se.p[inst->subid].p2 = p;
6253e12c5d1SDavid du Colombier inst = inst->next;
6263e12c5d1SDavid du Colombier goto Switchstmt;
6273e12c5d1SDavid du Colombier case ANY:
6283e12c5d1SDavid du Colombier if(c!='\n')
6293e12c5d1SDavid du Colombier goto Addinst;
6303e12c5d1SDavid du Colombier break;
6313e12c5d1SDavid du Colombier case BOL:
6327dd7cddfSDavid du Colombier if(p==0 || filereadc(f, p - 1)=='\n'){
6333e12c5d1SDavid du Colombier Step:
6343e12c5d1SDavid du Colombier inst = inst->next;
6353e12c5d1SDavid du Colombier goto Switchstmt;
6363e12c5d1SDavid du Colombier }
6373e12c5d1SDavid du Colombier break;
6383e12c5d1SDavid du Colombier case EOL:
6393e12c5d1SDavid du Colombier if(c == '\n')
6403e12c5d1SDavid du Colombier goto Step;
6413e12c5d1SDavid du Colombier break;
6423e12c5d1SDavid du Colombier case CCLASS:
6433e12c5d1SDavid du Colombier if(c>=0 && classmatch(inst->rclass, c, 0))
6443e12c5d1SDavid du Colombier goto Addinst;
6453e12c5d1SDavid du Colombier break;
6463e12c5d1SDavid du Colombier case NCCLASS:
6473e12c5d1SDavid du Colombier if(c>=0 && classmatch(inst->rclass, c, 1))
6483e12c5d1SDavid du Colombier goto Addinst;
6493e12c5d1SDavid du Colombier break;
6503e12c5d1SDavid du Colombier case OR:
6513e12c5d1SDavid du Colombier /* evaluate right choice later */
652e7f22645SDavid du Colombier if(addinst(tlp, inst->right, &tlp->se))
6533e12c5d1SDavid du Colombier if(++ntl >= NLIST)
6543e12c5d1SDavid du Colombier goto Overflow;
6553e12c5d1SDavid du Colombier /* efficiency: advance and re-evaluate */
6563e12c5d1SDavid du Colombier inst = inst->left;
6573e12c5d1SDavid du Colombier goto Switchstmt;
6583e12c5d1SDavid du Colombier case END: /* Match! */
6593e12c5d1SDavid du Colombier tlp->se.p[0].p2 = p;
6603e12c5d1SDavid du Colombier newmatch(&tlp->se);
6613e12c5d1SDavid du Colombier break;
6623e12c5d1SDavid du Colombier }
6633e12c5d1SDavid du Colombier }
6643e12c5d1SDavid du Colombier }
6653e12c5d1SDavid du Colombier Return:
6663e12c5d1SDavid du Colombier return sel.p[0].p1>=0;
6673e12c5d1SDavid du Colombier }
6683e12c5d1SDavid du Colombier
6693e12c5d1SDavid du Colombier void
newmatch(Rangeset * sp)6703e12c5d1SDavid du Colombier newmatch(Rangeset *sp)
6713e12c5d1SDavid du Colombier {
6723e12c5d1SDavid du Colombier int i;
6733e12c5d1SDavid du Colombier
6743e12c5d1SDavid du Colombier if(sel.p[0].p1<0 || sp->p[0].p1<sel.p[0].p1 ||
6753e12c5d1SDavid du Colombier (sp->p[0].p1==sel.p[0].p1 && sp->p[0].p2>sel.p[0].p2))
6763e12c5d1SDavid du Colombier for(i = 0; i<NSUBEXP; i++)
6773e12c5d1SDavid du Colombier sel.p[i] = sp->p[i];
6783e12c5d1SDavid du Colombier }
6793e12c5d1SDavid du Colombier
6803e12c5d1SDavid du Colombier int
bexecute(File * f,Posn startp)6813e12c5d1SDavid du Colombier bexecute(File *f, Posn startp)
6823e12c5d1SDavid du Colombier {
6833e12c5d1SDavid du Colombier int flag = 0;
6843e12c5d1SDavid du Colombier Inst *inst;
6853e12c5d1SDavid du Colombier Ilist *tlp;
6863e12c5d1SDavid du Colombier Posn p = startp;
6873e12c5d1SDavid du Colombier int nnl = 0, ntl;
6883e12c5d1SDavid du Colombier int c;
6893e12c5d1SDavid du Colombier int wrapped = 0;
6903e12c5d1SDavid du Colombier int startchar = bstartinst->type<OPERATOR? bstartinst->type : 0;
6913e12c5d1SDavid du Colombier
6923e12c5d1SDavid du Colombier list[0][0].inst = list[1][0].inst = 0;
6933e12c5d1SDavid du Colombier sel.p[0].p1= -1;
6943e12c5d1SDavid du Colombier /* Execute machine once for each character, including terminal NUL */
6953e12c5d1SDavid du Colombier for(;;--p){
6963e12c5d1SDavid du Colombier doloop:
6977dd7cddfSDavid du Colombier if((c = filereadc(f, p - 1))==-1){
6983e12c5d1SDavid du Colombier switch(wrapped++){
6993e12c5d1SDavid du Colombier case 0: /* let loop run one more click */
7003e12c5d1SDavid du Colombier case 2:
7013e12c5d1SDavid du Colombier break;
7023e12c5d1SDavid du Colombier case 1: /* expired; wrap to end */
7033e12c5d1SDavid du Colombier if(sel.p[0].p1>=0)
7043e12c5d1SDavid du Colombier case 3:
7053e12c5d1SDavid du Colombier goto Return;
7063e12c5d1SDavid du Colombier list[0][0].inst = list[1][0].inst = 0;
7077dd7cddfSDavid du Colombier p = f->nc;
7083e12c5d1SDavid du Colombier goto doloop;
7093e12c5d1SDavid du Colombier default:
7103e12c5d1SDavid du Colombier goto Return;
7113e12c5d1SDavid du Colombier }
7123e12c5d1SDavid du Colombier }else if(((wrapped && p<=startp) || sel.p[0].p1>0) && nnl==0)
7133e12c5d1SDavid du Colombier break;
7143e12c5d1SDavid du Colombier /* fast check for first char */
7153e12c5d1SDavid du Colombier if(startchar && nnl==0 && c!=startchar)
7163e12c5d1SDavid du Colombier continue;
7173e12c5d1SDavid du Colombier tl = list[flag];
7183e12c5d1SDavid du Colombier nl = list[flag^=1];
7193e12c5d1SDavid du Colombier nl->inst = 0;
7203e12c5d1SDavid du Colombier ntl = nnl;
7213e12c5d1SDavid du Colombier nnl = 0;
7223e12c5d1SDavid du Colombier if(sel.p[0].p1<0 && (!wrapped || p>startp)){
7233e12c5d1SDavid du Colombier /* Add first instruction to this list */
724e6dcbf51SDavid du Colombier /* the minus is so the optimizations in addinst work */
725e6dcbf51SDavid du Colombier sempty.p[0].p1 = -p;
726e6dcbf51SDavid du Colombier if(addinst(tl, bstartinst, &sempty))
7273e12c5d1SDavid du Colombier if(++ntl >= NLIST)
7283e12c5d1SDavid du Colombier Overflow:
7293e12c5d1SDavid du Colombier error(Eoverflow);
7303e12c5d1SDavid du Colombier }
7313e12c5d1SDavid du Colombier /* Execute machine until this list is empty */
7323e12c5d1SDavid du Colombier for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment = */
7333e12c5d1SDavid du Colombier Switchstmt:
7343e12c5d1SDavid du Colombier switch(inst->type){
7353e12c5d1SDavid du Colombier default: /* regular character */
7363e12c5d1SDavid du Colombier if(inst->type == c){
7373e12c5d1SDavid du Colombier Addinst:
738e6dcbf51SDavid du Colombier if(addinst(nl, inst->next, &tlp->se))
7393e12c5d1SDavid du Colombier if(++nnl >= NLIST)
7403e12c5d1SDavid du Colombier goto Overflow;
7413e12c5d1SDavid du Colombier }
7423e12c5d1SDavid du Colombier break;
7433e12c5d1SDavid du Colombier case LBRA:
7443e12c5d1SDavid du Colombier if(inst->subid>=0)
7453e12c5d1SDavid du Colombier tlp->se.p[inst->subid].p1 = p;
7463e12c5d1SDavid du Colombier inst = inst->next;
7473e12c5d1SDavid du Colombier goto Switchstmt;
7483e12c5d1SDavid du Colombier case RBRA:
7493e12c5d1SDavid du Colombier if(inst->subid >= 0)
7503e12c5d1SDavid du Colombier tlp->se.p[inst->subid].p2 = p;
7513e12c5d1SDavid du Colombier inst = inst->next;
7523e12c5d1SDavid du Colombier goto Switchstmt;
7533e12c5d1SDavid du Colombier case ANY:
7543e12c5d1SDavid du Colombier if(c != '\n')
7553e12c5d1SDavid du Colombier goto Addinst;
7563e12c5d1SDavid du Colombier break;
7573e12c5d1SDavid du Colombier case BOL:
7583e12c5d1SDavid du Colombier if(c=='\n' || p==0){
7593e12c5d1SDavid du Colombier Step:
7603e12c5d1SDavid du Colombier inst = inst->next;
7613e12c5d1SDavid du Colombier goto Switchstmt;
7623e12c5d1SDavid du Colombier }
7633e12c5d1SDavid du Colombier break;
7643e12c5d1SDavid du Colombier case EOL:
7657dd7cddfSDavid du Colombier if(p==f->nc || filereadc(f, p)=='\n')
7663e12c5d1SDavid du Colombier goto Step;
7673e12c5d1SDavid du Colombier break;
7683e12c5d1SDavid du Colombier case CCLASS:
7693e12c5d1SDavid du Colombier if(c>=0 && classmatch(inst->rclass, c, 0))
7703e12c5d1SDavid du Colombier goto Addinst;
7713e12c5d1SDavid du Colombier break;
7723e12c5d1SDavid du Colombier case NCCLASS:
7733e12c5d1SDavid du Colombier if(c>=0 && classmatch(inst->rclass, c, 1))
7743e12c5d1SDavid du Colombier goto Addinst;
7753e12c5d1SDavid du Colombier break;
7763e12c5d1SDavid du Colombier case OR:
7773e12c5d1SDavid du Colombier /* evaluate right choice later */
778e6dcbf51SDavid du Colombier if(addinst(tl, inst->right, &tlp->se))
7793e12c5d1SDavid du Colombier if(++ntl >= NLIST)
7803e12c5d1SDavid du Colombier goto Overflow;
7813e12c5d1SDavid du Colombier /* efficiency: advance and re-evaluate */
7823e12c5d1SDavid du Colombier inst = inst->left;
7833e12c5d1SDavid du Colombier goto Switchstmt;
7843e12c5d1SDavid du Colombier case END: /* Match! */
7853e12c5d1SDavid du Colombier tlp->se.p[0].p1 = -tlp->se.p[0].p1; /* minus sign */
7863e12c5d1SDavid du Colombier tlp->se.p[0].p2 = p;
7873e12c5d1SDavid du Colombier bnewmatch(&tlp->se);
7883e12c5d1SDavid du Colombier break;
7893e12c5d1SDavid du Colombier }
7903e12c5d1SDavid du Colombier }
7913e12c5d1SDavid du Colombier }
7923e12c5d1SDavid du Colombier Return:
7933e12c5d1SDavid du Colombier return sel.p[0].p1>=0;
7943e12c5d1SDavid du Colombier }
7953e12c5d1SDavid du Colombier
7963e12c5d1SDavid du Colombier void
bnewmatch(Rangeset * sp)7973e12c5d1SDavid du Colombier bnewmatch(Rangeset *sp)
7983e12c5d1SDavid du Colombier {
7993e12c5d1SDavid du Colombier int i;
8003e12c5d1SDavid du Colombier if(sel.p[0].p1<0 || sp->p[0].p1>sel.p[0].p2 || (sp->p[0].p1==sel.p[0].p2 && sp->p[0].p2<sel.p[0].p1))
8013e12c5d1SDavid du Colombier for(i = 0; i<NSUBEXP; i++){ /* note the reversal; p1<=p2 */
8023e12c5d1SDavid du Colombier sel.p[i].p1 = sp->p[i].p2;
8033e12c5d1SDavid du Colombier sel.p[i].p2 = sp->p[i].p1;
8043e12c5d1SDavid du Colombier }
8053e12c5d1SDavid du Colombier }
806