regexp.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "sam.h"
  10. Rangeset sel;
  11. String lastregexp;
  12. /*
  13. * Machine Information
  14. */
  15. typedef struct Inst Inst;
  16. struct Inst
  17. {
  18. long type; /* <= Runemax ==> literal, otherwise action */
  19. union {
  20. int rsid;
  21. int rsubid;
  22. int class;
  23. struct Inst *rother;
  24. struct Inst *rright;
  25. } r;
  26. union{
  27. struct Inst *lleft;
  28. struct Inst *lnext;
  29. } l;
  30. };
  31. #define sid r.rsid
  32. #define subid r.rsubid
  33. #define rclass r.class
  34. #define other r.rother
  35. #define right r.rright
  36. #define left l.lleft
  37. #define next l.lnext
  38. #define NPROG 1024
  39. Inst program[NPROG];
  40. Inst *progp;
  41. Inst *startinst; /* First inst. of program; might not be program[0] */
  42. Inst *bstartinst; /* same for backwards machine */
  43. typedef struct Ilist Ilist;
  44. struct Ilist
  45. {
  46. Inst *inst; /* Instruction of the thread */
  47. Rangeset se;
  48. Posn startp; /* first char of match */
  49. };
  50. #define NLIST 127
  51. Ilist *tl, *nl; /* This list, next list */
  52. Ilist list[2][NLIST+1]; /* +1 for trailing null */
  53. static Rangeset sempty;
  54. /*
  55. * Actions and Tokens
  56. *
  57. * 0x100xx are operators, value == precedence
  58. * 0x200xx are tokens, i.e. operands for operators
  59. */
  60. enum {
  61. OPERATOR = Runemask+1, /* Bitmask of all operators */
  62. START = OPERATOR, /* Start, used for marker on stack */
  63. RBRA, /* Right bracket, ) */
  64. LBRA, /* Left bracket, ( */
  65. OR, /* Alternation, | */
  66. CAT, /* Concatentation, implicit operator */
  67. STAR, /* Closure, * */
  68. PLUS, /* a+ == aa* */
  69. QUEST, /* a? == a|nothing, i.e. 0 or 1 a's */
  70. ANY = OPERATOR<<1, /* Any character but newline, . */
  71. NOP, /* No operation, internal use only */
  72. BOL, /* Beginning of line, ^ */
  73. EOL, /* End of line, $ */
  74. CCLASS, /* Character class, [] */
  75. NCCLASS, /* Negated character class, [^] */
  76. END, /* Terminate: match found */
  77. ISATOR = OPERATOR,
  78. ISAND = OPERATOR<<1,
  79. };
  80. /*
  81. * Parser Information
  82. */
  83. typedef struct Node Node;
  84. struct Node
  85. {
  86. Inst *first;
  87. Inst *last;
  88. };
  89. #define NSTACK 20
  90. Node andstack[NSTACK];
  91. Node *andp;
  92. int atorstack[NSTACK];
  93. int *atorp;
  94. int lastwasand; /* Last token was operand */
  95. int cursubid;
  96. int subidstack[NSTACK];
  97. int *subidp;
  98. int backwards;
  99. int nbra;
  100. Rune *exprp; /* pointer to next character in source expression */
  101. #define DCLASS 10 /* allocation increment */
  102. int nclass; /* number active */
  103. int Nclass; /* high water mark */
  104. Rune **class;
  105. int negateclass;
  106. int addinst(Ilist *l, Inst *inst, Rangeset *sep);
  107. void newmatch(Rangeset*);
  108. void bnewmatch(Rangeset*);
  109. void pushand(Inst*, Inst*);
  110. void pushator(int);
  111. Node *popand(int);
  112. int popator(void);
  113. void startlex(Rune*);
  114. int lex(void);
  115. void operator(int);
  116. void operand(int);
  117. void evaluntil(int);
  118. void optimize(Inst*);
  119. void bldcclass(void);
  120. void
  121. regerror(Err e)
  122. {
  123. Strzero(&lastregexp);
  124. error(e);
  125. }
  126. void
  127. regerror_c(Err e, int c)
  128. {
  129. Strzero(&lastregexp);
  130. error_c(e, c);
  131. }
  132. Inst *
  133. newinst(int t)
  134. {
  135. if(progp >= &program[NPROG])
  136. regerror(Etoolong);
  137. progp->type = t;
  138. progp->left = 0;
  139. progp->right = 0;
  140. return progp++;
  141. }
  142. Inst *
  143. realcompile(Rune *s)
  144. {
  145. int token;
  146. startlex(s);
  147. atorp = atorstack;
  148. andp = andstack;
  149. subidp = subidstack;
  150. cursubid = 0;
  151. lastwasand = FALSE;
  152. /* Start with a low priority operator to prime parser */
  153. pushator(START-1);
  154. while((token=lex()) != END){
  155. if((token&ISATOR) == OPERATOR)
  156. operator(token);
  157. else
  158. operand(token);
  159. }
  160. /* Close with a low priority operator */
  161. evaluntil(START);
  162. /* Force END */
  163. operand(END);
  164. evaluntil(START);
  165. if(nbra)
  166. regerror(Eleftpar);
  167. --andp; /* points to first and only operand */
  168. return andp->first;
  169. }
  170. void
  171. compile(String *s)
  172. {
  173. int i;
  174. Inst *oprogp;
  175. if(Strcmp(s, &lastregexp)==0)
  176. return;
  177. for(i=0; i<nclass; i++)
  178. free(class[i]);
  179. nclass = 0;
  180. progp = program;
  181. backwards = FALSE;
  182. startinst = realcompile(s->s);
  183. optimize(program);
  184. oprogp = progp;
  185. backwards = TRUE;
  186. bstartinst = realcompile(s->s);
  187. optimize(oprogp);
  188. Strduplstr(&lastregexp, s);
  189. }
  190. void
  191. operand(int t)
  192. {
  193. Inst *i;
  194. if(lastwasand)
  195. operator(CAT); /* catenate is implicit */
  196. i = newinst(t);
  197. if(t == CCLASS){
  198. if(negateclass)
  199. i->type = NCCLASS; /* UGH */
  200. i->rclass = nclass-1; /* UGH */
  201. }
  202. pushand(i, i);
  203. lastwasand = TRUE;
  204. }
  205. void
  206. operator(int t)
  207. {
  208. if(t==RBRA && --nbra<0)
  209. regerror(Erightpar);
  210. if(t==LBRA){
  211. /*
  212. * if(++cursubid >= NSUBEXP)
  213. * regerror(Esubexp);
  214. */
  215. cursubid++; /* silently ignored */
  216. nbra++;
  217. if(lastwasand)
  218. operator(CAT);
  219. }else
  220. evaluntil(t);
  221. if(t!=RBRA)
  222. pushator(t);
  223. lastwasand = FALSE;
  224. if(t==STAR || t==QUEST || t==PLUS || t==RBRA)
  225. lastwasand = TRUE; /* these look like operands */
  226. }
  227. void
  228. cant(char *s)
  229. {
  230. char buf[100];
  231. sprint(buf, "regexp: can't happen: %s", s);
  232. panic(buf);
  233. }
  234. void
  235. pushand(Inst *f, Inst *l)
  236. {
  237. if(andp >= &andstack[NSTACK])
  238. cant("operand stack overflow");
  239. andp->first = f;
  240. andp->last = l;
  241. andp++;
  242. }
  243. void
  244. pushator(int t)
  245. {
  246. if(atorp >= &atorstack[NSTACK])
  247. cant("operator stack overflow");
  248. *atorp++=t;
  249. if(cursubid >= NSUBEXP)
  250. *subidp++= -1;
  251. else
  252. *subidp++=cursubid;
  253. }
  254. Node *
  255. popand(int op)
  256. {
  257. if(andp <= &andstack[0]){
  258. if(op)
  259. regerror_c(Emissop, op);
  260. else
  261. regerror(Ebadregexp);
  262. }
  263. return --andp;
  264. }
  265. int
  266. popator(void)
  267. {
  268. if(atorp <= &atorstack[0])
  269. cant("operator stack underflow");
  270. --subidp;
  271. return *--atorp;
  272. }
  273. void
  274. evaluntil(int pri)
  275. {
  276. Node *op1, *op2, *t;
  277. Inst *inst1, *inst2;
  278. while(pri==RBRA || atorp[-1]>=pri){
  279. switch(popator()){
  280. case LBRA:
  281. op1 = popand('(');
  282. inst2 = newinst(RBRA);
  283. inst2->subid = *subidp;
  284. op1->last->next = inst2;
  285. inst1 = newinst(LBRA);
  286. inst1->subid = *subidp;
  287. inst1->next = op1->first;
  288. pushand(inst1, inst2);
  289. return; /* must have been RBRA */
  290. default:
  291. panic("unknown regexp operator");
  292. break;
  293. case OR:
  294. op2 = popand('|');
  295. op1 = popand('|');
  296. inst2 = newinst(NOP);
  297. op2->last->next = inst2;
  298. op1->last->next = inst2;
  299. inst1 = newinst(OR);
  300. inst1->right = op1->first;
  301. inst1->left = op2->first;
  302. pushand(inst1, inst2);
  303. break;
  304. case CAT:
  305. op2 = popand(0);
  306. op1 = popand(0);
  307. if(backwards && op2->first->type!=END)
  308. t = op1, op1 = op2, op2 = t;
  309. op1->last->next = op2->first;
  310. pushand(op1->first, op2->last);
  311. break;
  312. case STAR:
  313. op2 = popand('*');
  314. inst1 = newinst(OR);
  315. op2->last->next = inst1;
  316. inst1->right = op2->first;
  317. pushand(inst1, inst1);
  318. break;
  319. case PLUS:
  320. op2 = popand('+');
  321. inst1 = newinst(OR);
  322. op2->last->next = inst1;
  323. inst1->right = op2->first;
  324. pushand(op2->first, inst1);
  325. break;
  326. case QUEST:
  327. op2 = popand('?');
  328. inst1 = newinst(OR);
  329. inst2 = newinst(NOP);
  330. inst1->left = inst2;
  331. inst1->right = op2->first;
  332. op2->last->next = inst2;
  333. pushand(inst1, inst2);
  334. break;
  335. }
  336. }
  337. }
  338. void
  339. optimize(Inst *start)
  340. {
  341. Inst *inst, *target;
  342. for(inst=start; inst->type!=END; inst++){
  343. target = inst->next;
  344. while(target->type == NOP)
  345. target = target->next;
  346. inst->next = target;
  347. }
  348. }
  349. #ifdef DEBUG
  350. void
  351. dumpstack(void){
  352. Node *stk;
  353. int *ip;
  354. dprint("operators\n");
  355. for(ip = atorstack; ip<atorp; ip++)
  356. dprint("0%o\n", *ip);
  357. dprint("operands\n");
  358. for(stk = andstack; stk<andp; stk++)
  359. dprint("0%o\t0%o\n", stk->first->type, stk->last->type);
  360. }
  361. void
  362. dump(void){
  363. Inst *l;
  364. l = program;
  365. do{
  366. dprint("%d:\t0%o\t%d\t%d\n", l-program, l->type,
  367. l->left-program, l->right-program);
  368. }while(l++->type);
  369. }
  370. #endif
  371. void
  372. startlex(Rune *s)
  373. {
  374. exprp = s;
  375. nbra = 0;
  376. }
  377. int
  378. lex(void){
  379. int c= *exprp++;
  380. switch(c){
  381. case '\\':
  382. if(*exprp)
  383. if((c= *exprp++)=='n')
  384. c='\n';
  385. break;
  386. case 0:
  387. c = END;
  388. --exprp; /* In case we come here again */
  389. break;
  390. case '*':
  391. c = STAR;
  392. break;
  393. case '?':
  394. c = QUEST;
  395. break;
  396. case '+':
  397. c = PLUS;
  398. break;
  399. case '|':
  400. c = OR;
  401. break;
  402. case '.':
  403. c = ANY;
  404. break;
  405. case '(':
  406. c = LBRA;
  407. break;
  408. case ')':
  409. c = RBRA;
  410. break;
  411. case '^':
  412. c = BOL;
  413. break;
  414. case '$':
  415. c = EOL;
  416. break;
  417. case '[':
  418. c = CCLASS;
  419. bldcclass();
  420. break;
  421. }
  422. return c;
  423. }
  424. long
  425. nextrec(void){
  426. if(exprp[0]==0 || (exprp[0]=='\\' && exprp[1]==0))
  427. regerror(Ebadclass);
  428. if(exprp[0] == '\\'){
  429. exprp++;
  430. if(*exprp=='n'){
  431. exprp++;
  432. return '\n';
  433. }
  434. return *exprp++|(Runemax+1);
  435. }
  436. return *exprp++;
  437. }
  438. void
  439. bldcclass(void)
  440. {
  441. long c1, c2, n, na;
  442. Rune *classp;
  443. classp = emalloc(DCLASS*RUNESIZE);
  444. n = 0;
  445. na = DCLASS;
  446. /* we have already seen the '[' */
  447. if(*exprp == '^'){
  448. classp[n++] = '\n'; /* don't match newline in negate case */
  449. negateclass = TRUE;
  450. exprp++;
  451. }else
  452. negateclass = FALSE;
  453. while((c1 = nextrec()) != ']'){
  454. if(c1 == '-'){
  455. Error:
  456. free(classp);
  457. regerror(Ebadclass);
  458. }
  459. if(n+4 >= na){ /* 3 runes plus NUL */
  460. na += DCLASS;
  461. classp = erealloc(classp, na*RUNESIZE);
  462. }
  463. if(*exprp == '-'){
  464. exprp++; /* eat '-' */
  465. if((c2 = nextrec()) == ']')
  466. goto Error;
  467. classp[n+0] = Runemax;
  468. classp[n+1] = c1;
  469. classp[n+2] = c2;
  470. n += 3;
  471. }else
  472. classp[n++] = c1;
  473. }
  474. classp[n] = 0;
  475. if(nclass == Nclass){
  476. Nclass += DCLASS;
  477. class = erealloc(class, Nclass*sizeof(Rune*));
  478. }
  479. class[nclass++] = classp;
  480. }
  481. int
  482. classmatch(int classno, int c, int negate)
  483. {
  484. Rune *p;
  485. p = class[classno];
  486. while(*p){
  487. if(*p == Runemax){
  488. if(p[1]<=c && c<=p[2])
  489. return !negate;
  490. p += 3;
  491. }else if(*p++ == c)
  492. return !negate;
  493. }
  494. return negate;
  495. }
  496. /*
  497. * Note optimization in addinst:
  498. * *l must be pending when addinst called; if *l has been looked
  499. * at already, the optimization is a bug.
  500. */
  501. int
  502. addinst(Ilist *l, Inst *inst, Rangeset *sep)
  503. {
  504. Ilist *p;
  505. for(p = l; p->inst; p++){
  506. if(p->inst==inst){
  507. if((sep)->p[0].p1 < p->se.p[0].p1)
  508. p->se= *sep; /* this would be bug */
  509. return 0; /* It's already there */
  510. }
  511. }
  512. p->inst = inst;
  513. p->se= *sep;
  514. (p+1)->inst = 0;
  515. return 1;
  516. }
  517. int
  518. execute(File *f, Posn startp, Posn eof)
  519. {
  520. int flag = 0;
  521. Inst *inst;
  522. Ilist *tlp;
  523. Posn p = startp;
  524. int nnl = 0, ntl;
  525. int c;
  526. int wrapped = 0;
  527. int startchar = startinst->type<OPERATOR? startinst->type : 0;
  528. list[0][0].inst = list[1][0].inst = 0;
  529. sel.p[0].p1 = -1;
  530. /* Execute machine once for each character */
  531. for(;;p++){
  532. doloop:
  533. c = filereadc(f, p);
  534. if(p>=eof || c<0){
  535. switch(wrapped++){
  536. case 0: /* let loop run one more click */
  537. case 2:
  538. break;
  539. case 1: /* expired; wrap to beginning */
  540. if(sel.p[0].p1>=0 || eof!=INFINITY)
  541. goto Return;
  542. list[0][0].inst = list[1][0].inst = 0;
  543. p = 0;
  544. goto doloop;
  545. default:
  546. goto Return;
  547. }
  548. }else if(((wrapped && p>=startp) || sel.p[0].p1>0) && nnl==0)
  549. break;
  550. /* fast check for first char */
  551. if(startchar && nnl==0 && c!=startchar)
  552. continue;
  553. tl = list[flag];
  554. nl = list[flag^=1];
  555. nl->inst = 0;
  556. ntl = nnl;
  557. nnl = 0;
  558. if(sel.p[0].p1<0 && (!wrapped || p<startp || startp==eof)){
  559. /* Add first instruction to this list */
  560. sempty.p[0].p1 = p;
  561. if(addinst(tl, startinst, &sempty))
  562. if(++ntl >= NLIST)
  563. Overflow:
  564. error(Eoverflow);
  565. }
  566. /* Execute machine until this list is empty */
  567. for(tlp = tl; (inst = tlp->inst) != nil; tlp++){
  568. Switchstmt:
  569. switch(inst->type){
  570. default: /* regular character */
  571. if(inst->type==c){
  572. Addinst:
  573. if(addinst(nl, inst->next, &tlp->se))
  574. if(++nnl >= NLIST)
  575. goto Overflow;
  576. }
  577. break;
  578. case LBRA:
  579. if(inst->subid>=0)
  580. tlp->se.p[inst->subid].p1 = p;
  581. inst = inst->next;
  582. goto Switchstmt;
  583. case RBRA:
  584. if(inst->subid>=0)
  585. tlp->se.p[inst->subid].p2 = p;
  586. inst = inst->next;
  587. goto Switchstmt;
  588. case ANY:
  589. if(c!='\n')
  590. goto Addinst;
  591. break;
  592. case BOL:
  593. if(p==0 || filereadc(f, p - 1)=='\n'){
  594. Step:
  595. inst = inst->next;
  596. goto Switchstmt;
  597. }
  598. break;
  599. case EOL:
  600. if(c == '\n')
  601. goto Step;
  602. break;
  603. case CCLASS:
  604. if(c>=0 && classmatch(inst->rclass, c, 0))
  605. goto Addinst;
  606. break;
  607. case NCCLASS:
  608. if(c>=0 && classmatch(inst->rclass, c, 1))
  609. goto Addinst;
  610. break;
  611. case OR:
  612. /* evaluate right choice later */
  613. if(addinst(tlp, inst->right, &tlp->se))
  614. if(++ntl >= NLIST)
  615. goto Overflow;
  616. /* efficiency: advance and re-evaluate */
  617. inst = inst->left;
  618. goto Switchstmt;
  619. case END: /* Match! */
  620. tlp->se.p[0].p2 = p;
  621. newmatch(&tlp->se);
  622. break;
  623. }
  624. }
  625. }
  626. Return:
  627. return sel.p[0].p1>=0;
  628. }
  629. void
  630. newmatch(Rangeset *sp)
  631. {
  632. int i;
  633. if(sel.p[0].p1<0 || sp->p[0].p1<sel.p[0].p1 ||
  634. (sp->p[0].p1==sel.p[0].p1 && sp->p[0].p2>sel.p[0].p2))
  635. for(i = 0; i<NSUBEXP; i++)
  636. sel.p[i] = sp->p[i];
  637. }
  638. int
  639. bexecute(File *f, Posn startp)
  640. {
  641. int flag = 0;
  642. Inst *inst;
  643. Ilist *tlp;
  644. Posn p = startp;
  645. int nnl = 0, ntl;
  646. int c;
  647. int wrapped = 0;
  648. int startchar = bstartinst->type<OPERATOR? bstartinst->type : 0;
  649. list[0][0].inst = list[1][0].inst = 0;
  650. sel.p[0].p1= -1;
  651. /* Execute machine once for each character, including terminal NUL */
  652. for(;;--p){
  653. doloop:
  654. if((c = filereadc(f, p - 1))==-1){
  655. switch(wrapped++){
  656. case 0: /* let loop run one more click */
  657. case 2:
  658. break;
  659. case 1: /* expired; wrap to end */
  660. if(sel.p[0].p1>=0)
  661. case 3:
  662. goto Return;
  663. list[0][0].inst = list[1][0].inst = 0;
  664. p = f->Buffer.nc;
  665. goto doloop;
  666. default:
  667. goto Return;
  668. }
  669. }else if(((wrapped && p<=startp) || sel.p[0].p1>0) && nnl==0)
  670. break;
  671. /* fast check for first char */
  672. if(startchar && nnl==0 && c!=startchar)
  673. continue;
  674. tl = list[flag];
  675. nl = list[flag^=1];
  676. nl->inst = 0;
  677. ntl = nnl;
  678. nnl = 0;
  679. if(sel.p[0].p1<0 && (!wrapped || p>startp)){
  680. /* Add first instruction to this list */
  681. /* the minus is so the optimizations in addinst work */
  682. sempty.p[0].p1 = -p;
  683. if(addinst(tl, bstartinst, &sempty))
  684. if(++ntl >= NLIST)
  685. Overflow:
  686. error(Eoverflow);
  687. }
  688. /* Execute machine until this list is empty */
  689. for(tlp = tl; (inst = tlp->inst) != nil; tlp++){
  690. Switchstmt:
  691. switch(inst->type){
  692. default: /* regular character */
  693. if(inst->type == c){
  694. Addinst:
  695. if(addinst(nl, inst->next, &tlp->se))
  696. if(++nnl >= NLIST)
  697. goto Overflow;
  698. }
  699. break;
  700. case LBRA:
  701. if(inst->subid>=0)
  702. tlp->se.p[inst->subid].p1 = p;
  703. inst = inst->next;
  704. goto Switchstmt;
  705. case RBRA:
  706. if(inst->subid >= 0)
  707. tlp->se.p[inst->subid].p2 = p;
  708. inst = inst->next;
  709. goto Switchstmt;
  710. case ANY:
  711. if(c != '\n')
  712. goto Addinst;
  713. break;
  714. case BOL:
  715. if(c=='\n' || p==0){
  716. Step:
  717. inst = inst->next;
  718. goto Switchstmt;
  719. }
  720. break;
  721. case EOL:
  722. if(p==f->Buffer.nc || filereadc(f, p)=='\n')
  723. goto Step;
  724. break;
  725. case CCLASS:
  726. if(c>=0 && classmatch(inst->rclass, c, 0))
  727. goto Addinst;
  728. break;
  729. case NCCLASS:
  730. if(c>=0 && classmatch(inst->rclass, c, 1))
  731. goto Addinst;
  732. break;
  733. case OR:
  734. /* evaluate right choice later */
  735. if(addinst(tl, inst->right, &tlp->se))
  736. if(++ntl >= NLIST)
  737. goto Overflow;
  738. /* efficiency: advance and re-evaluate */
  739. inst = inst->left;
  740. goto Switchstmt;
  741. case END: /* Match! */
  742. tlp->se.p[0].p1 = -tlp->se.p[0].p1; /* minus sign */
  743. tlp->se.p[0].p2 = p;
  744. bnewmatch(&tlp->se);
  745. break;
  746. }
  747. }
  748. }
  749. Return:
  750. return sel.p[0].p1>=0;
  751. }
  752. void
  753. bnewmatch(Rangeset *sp)
  754. {
  755. int i;
  756. 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))
  757. for(i = 0; i<NSUBEXP; i++){ /* note the reversal; p1<=p2 */
  758. sel.p[i].p1 = sp->p[i].p2;
  759. sel.p[i].p2 = sp->p[i].p1;
  760. }
  761. }