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