regexp.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  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. return --andp;
  263. }
  264. int
  265. popator(void)
  266. {
  267. if(atorp <= &atorstack[0])
  268. cant("operator stack underflow");
  269. --subidp;
  270. return *--atorp;
  271. }
  272. void
  273. evaluntil(int pri)
  274. {
  275. Node *op1, *op2, *t;
  276. Inst *inst1, *inst2;
  277. while(pri==RBRA || atorp[-1]>=pri){
  278. switch(popator()){
  279. case LBRA:
  280. op1 = popand('(');
  281. inst2 = newinst(RBRA);
  282. inst2->subid = *subidp;
  283. op1->last->next = inst2;
  284. inst1 = newinst(LBRA);
  285. inst1->subid = *subidp;
  286. inst1->next = op1->first;
  287. pushand(inst1, inst2);
  288. return; /* must have been RBRA */
  289. default:
  290. panic("unknown regexp operator");
  291. break;
  292. case OR:
  293. op2 = popand('|');
  294. op1 = popand('|');
  295. inst2 = newinst(NOP);
  296. op2->last->next = inst2;
  297. op1->last->next = inst2;
  298. inst1 = newinst(OR);
  299. inst1->right = op1->first;
  300. inst1->left = op2->first;
  301. pushand(inst1, inst2);
  302. break;
  303. case CAT:
  304. op2 = popand(0);
  305. op1 = popand(0);
  306. if(backwards && op2->first->type!=END)
  307. t = op1, op1 = op2, op2 = t;
  308. op1->last->next = op2->first;
  309. pushand(op1->first, op2->last);
  310. break;
  311. case STAR:
  312. op2 = popand('*');
  313. inst1 = newinst(OR);
  314. op2->last->next = inst1;
  315. inst1->right = op2->first;
  316. pushand(inst1, inst1);
  317. break;
  318. case PLUS:
  319. op2 = popand('+');
  320. inst1 = newinst(OR);
  321. op2->last->next = inst1;
  322. inst1->right = op2->first;
  323. pushand(op2->first, inst1);
  324. break;
  325. case QUEST:
  326. op2 = popand('?');
  327. inst1 = newinst(OR);
  328. inst2 = newinst(NOP);
  329. inst1->left = inst2;
  330. inst1->right = op2->first;
  331. op2->last->next = inst2;
  332. pushand(inst1, inst2);
  333. break;
  334. }
  335. }
  336. }
  337. void
  338. optimize(Inst *start)
  339. {
  340. Inst *inst, *target;
  341. for(inst=start; inst->type!=END; inst++){
  342. target = inst->next;
  343. while(target->type == NOP)
  344. target = target->next;
  345. inst->next = target;
  346. }
  347. }
  348. #ifdef DEBUG
  349. void
  350. dumpstack(void){
  351. Node *stk;
  352. int *ip;
  353. dprint("operators\n");
  354. for(ip = atorstack; ip<atorp; ip++)
  355. dprint("0%o\n", *ip);
  356. dprint("operands\n");
  357. for(stk = andstack; stk<andp; stk++)
  358. dprint("0%o\t0%o\n", stk->first->type, stk->last->type);
  359. }
  360. void
  361. dump(void){
  362. Inst *l;
  363. l = program;
  364. do{
  365. dprint("%d:\t0%o\t%d\t%d\n", l-program, l->type,
  366. l->left-program, l->right-program);
  367. }while(l++->type);
  368. }
  369. #endif
  370. void
  371. startlex(Rune *s)
  372. {
  373. exprp = s;
  374. nbra = 0;
  375. }
  376. int
  377. lex(void){
  378. int c= *exprp++;
  379. switch(c){
  380. case '\\':
  381. if(*exprp)
  382. if((c= *exprp++)=='n')
  383. c='\n';
  384. break;
  385. case 0:
  386. c = END;
  387. --exprp; /* In case we come here again */
  388. break;
  389. case '*':
  390. c = STAR;
  391. break;
  392. case '?':
  393. c = QUEST;
  394. break;
  395. case '+':
  396. c = PLUS;
  397. break;
  398. case '|':
  399. c = OR;
  400. break;
  401. case '.':
  402. c = ANY;
  403. break;
  404. case '(':
  405. c = LBRA;
  406. break;
  407. case ')':
  408. c = RBRA;
  409. break;
  410. case '^':
  411. c = BOL;
  412. break;
  413. case '$':
  414. c = EOL;
  415. break;
  416. case '[':
  417. c = CCLASS;
  418. bldcclass();
  419. break;
  420. }
  421. return c;
  422. }
  423. long
  424. nextrec(void){
  425. if(exprp[0]==0 || (exprp[0]=='\\' && exprp[1]==0))
  426. regerror(Ebadclass);
  427. if(exprp[0] == '\\'){
  428. exprp++;
  429. if(*exprp=='n'){
  430. exprp++;
  431. return '\n';
  432. }
  433. return *exprp++|(Runemax+1);
  434. }
  435. return *exprp++;
  436. }
  437. void
  438. bldcclass(void)
  439. {
  440. long c1, c2, n, na;
  441. Rune *classp;
  442. classp = emalloc(DCLASS*RUNESIZE);
  443. n = 0;
  444. na = DCLASS;
  445. /* we have already seen the '[' */
  446. if(*exprp == '^'){
  447. classp[n++] = '\n'; /* don't match newline in negate case */
  448. negateclass = TRUE;
  449. exprp++;
  450. }else
  451. negateclass = FALSE;
  452. while((c1 = nextrec()) != ']'){
  453. if(c1 == '-'){
  454. Error:
  455. free(classp);
  456. regerror(Ebadclass);
  457. }
  458. if(n+4 >= na){ /* 3 runes plus NUL */
  459. na += DCLASS;
  460. classp = erealloc(classp, na*RUNESIZE);
  461. }
  462. if(*exprp == '-'){
  463. exprp++; /* eat '-' */
  464. if((c2 = nextrec()) == ']')
  465. goto Error;
  466. classp[n+0] = Runemax;
  467. classp[n+1] = c1;
  468. classp[n+2] = c2;
  469. n += 3;
  470. }else
  471. classp[n++] = c1;
  472. }
  473. classp[n] = 0;
  474. if(nclass == Nclass){
  475. Nclass += DCLASS;
  476. class = erealloc(class, Nclass*sizeof(Rune*));
  477. }
  478. class[nclass++] = classp;
  479. }
  480. int
  481. classmatch(int classno, int c, int negate)
  482. {
  483. Rune *p;
  484. p = class[classno];
  485. while(*p){
  486. if(*p == Runemax){
  487. if(p[1]<=c && c<=p[2])
  488. return !negate;
  489. p += 3;
  490. }else if(*p++ == c)
  491. return !negate;
  492. }
  493. return negate;
  494. }
  495. /*
  496. * Note optimization in addinst:
  497. * *l must be pending when addinst called; if *l has been looked
  498. * at already, the optimization is a bug.
  499. */
  500. int
  501. addinst(Ilist *l, Inst *inst, Rangeset *sep)
  502. {
  503. Ilist *p;
  504. for(p = l; p->inst; p++){
  505. if(p->inst==inst){
  506. if((sep)->p[0].p1 < p->se.p[0].p1)
  507. p->se= *sep; /* this would be bug */
  508. return 0; /* It's already there */
  509. }
  510. }
  511. p->inst = inst;
  512. p->se= *sep;
  513. (p+1)->inst = 0;
  514. return 1;
  515. }
  516. int
  517. execute(File *f, Posn startp, Posn eof)
  518. {
  519. int flag = 0;
  520. Inst *inst;
  521. Ilist *tlp;
  522. Posn p = startp;
  523. int nnl = 0, ntl;
  524. int c;
  525. int wrapped = 0;
  526. int startchar = startinst->type<OPERATOR? startinst->type : 0;
  527. list[0][0].inst = list[1][0].inst = 0;
  528. sel.p[0].p1 = -1;
  529. /* Execute machine once for each character */
  530. for(;;p++){
  531. doloop:
  532. c = filereadc(f, p);
  533. if(p>=eof || c<0){
  534. switch(wrapped++){
  535. case 0: /* let loop run one more click */
  536. case 2:
  537. break;
  538. case 1: /* expired; wrap to beginning */
  539. if(sel.p[0].p1>=0 || eof!=INFINITY)
  540. goto Return;
  541. list[0][0].inst = list[1][0].inst = 0;
  542. p = 0;
  543. goto doloop;
  544. default:
  545. goto Return;
  546. }
  547. }else if(((wrapped && p>=startp) || sel.p[0].p1>0) && nnl==0)
  548. break;
  549. /* fast check for first char */
  550. if(startchar && nnl==0 && c!=startchar)
  551. continue;
  552. tl = list[flag];
  553. nl = list[flag^=1];
  554. nl->inst = 0;
  555. ntl = nnl;
  556. nnl = 0;
  557. if(sel.p[0].p1<0 && (!wrapped || p<startp || startp==eof)){
  558. /* Add first instruction to this list */
  559. sempty.p[0].p1 = p;
  560. if(addinst(tl, startinst, &sempty))
  561. if(++ntl >= NLIST)
  562. Overflow:
  563. error(Eoverflow);
  564. }
  565. /* Execute machine until this list is empty */
  566. for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment = */
  567. Switchstmt:
  568. switch(inst->type){
  569. default: /* regular character */
  570. if(inst->type==c){
  571. Addinst:
  572. if(addinst(nl, inst->next, &tlp->se))
  573. if(++nnl >= NLIST)
  574. goto Overflow;
  575. }
  576. break;
  577. case LBRA:
  578. if(inst->subid>=0)
  579. tlp->se.p[inst->subid].p1 = p;
  580. inst = inst->next;
  581. goto Switchstmt;
  582. case RBRA:
  583. if(inst->subid>=0)
  584. tlp->se.p[inst->subid].p2 = p;
  585. inst = inst->next;
  586. goto Switchstmt;
  587. case ANY:
  588. if(c!='\n')
  589. goto Addinst;
  590. break;
  591. case BOL:
  592. if(p==0 || filereadc(f, p - 1)=='\n'){
  593. Step:
  594. inst = inst->next;
  595. goto Switchstmt;
  596. }
  597. break;
  598. case EOL:
  599. if(c == '\n')
  600. goto Step;
  601. break;
  602. case CCLASS:
  603. if(c>=0 && classmatch(inst->rclass, c, 0))
  604. goto Addinst;
  605. break;
  606. case NCCLASS:
  607. if(c>=0 && classmatch(inst->rclass, c, 1))
  608. goto Addinst;
  609. break;
  610. case OR:
  611. /* evaluate right choice later */
  612. if(addinst(tlp, inst->right, &tlp->se))
  613. if(++ntl >= NLIST)
  614. goto Overflow;
  615. /* efficiency: advance and re-evaluate */
  616. inst = inst->left;
  617. goto Switchstmt;
  618. case END: /* Match! */
  619. tlp->se.p[0].p2 = p;
  620. newmatch(&tlp->se);
  621. break;
  622. }
  623. }
  624. }
  625. Return:
  626. return sel.p[0].p1>=0;
  627. }
  628. void
  629. newmatch(Rangeset *sp)
  630. {
  631. int i;
  632. if(sel.p[0].p1<0 || sp->p[0].p1<sel.p[0].p1 ||
  633. (sp->p[0].p1==sel.p[0].p1 && sp->p[0].p2>sel.p[0].p2))
  634. for(i = 0; i<NSUBEXP; i++)
  635. sel.p[i] = sp->p[i];
  636. }
  637. int
  638. bexecute(File *f, Posn startp)
  639. {
  640. int flag = 0;
  641. Inst *inst;
  642. Ilist *tlp;
  643. Posn p = startp;
  644. int nnl = 0, ntl;
  645. int c;
  646. int wrapped = 0;
  647. int startchar = bstartinst->type<OPERATOR? bstartinst->type : 0;
  648. list[0][0].inst = list[1][0].inst = 0;
  649. sel.p[0].p1= -1;
  650. /* Execute machine once for each character, including terminal NUL */
  651. for(;;--p){
  652. doloop:
  653. if((c = filereadc(f, p - 1))==-1){
  654. switch(wrapped++){
  655. case 0: /* let loop run one more click */
  656. case 2:
  657. break;
  658. case 1: /* expired; wrap to end */
  659. if(sel.p[0].p1>=0)
  660. case 3:
  661. goto Return;
  662. list[0][0].inst = list[1][0].inst = 0;
  663. p = f->Buffer.nc;
  664. goto doloop;
  665. default:
  666. goto Return;
  667. }
  668. }else if(((wrapped && p<=startp) || sel.p[0].p1>0) && nnl==0)
  669. break;
  670. /* fast check for first char */
  671. if(startchar && nnl==0 && c!=startchar)
  672. continue;
  673. tl = list[flag];
  674. nl = list[flag^=1];
  675. nl->inst = 0;
  676. ntl = nnl;
  677. nnl = 0;
  678. if(sel.p[0].p1<0 && (!wrapped || p>startp)){
  679. /* Add first instruction to this list */
  680. /* the minus is so the optimizations in addinst work */
  681. sempty.p[0].p1 = -p;
  682. if(addinst(tl, bstartinst, &sempty))
  683. if(++ntl >= NLIST)
  684. Overflow:
  685. error(Eoverflow);
  686. }
  687. /* Execute machine until this list is empty */
  688. for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment = */
  689. Switchstmt:
  690. switch(inst->type){
  691. default: /* regular character */
  692. if(inst->type == c){
  693. Addinst:
  694. if(addinst(nl, inst->next, &tlp->se))
  695. if(++nnl >= NLIST)
  696. goto Overflow;
  697. }
  698. break;
  699. case LBRA:
  700. if(inst->subid>=0)
  701. tlp->se.p[inst->subid].p1 = p;
  702. inst = inst->next;
  703. goto Switchstmt;
  704. case RBRA:
  705. if(inst->subid >= 0)
  706. tlp->se.p[inst->subid].p2 = p;
  707. inst = inst->next;
  708. goto Switchstmt;
  709. case ANY:
  710. if(c != '\n')
  711. goto Addinst;
  712. break;
  713. case BOL:
  714. if(c=='\n' || p==0){
  715. Step:
  716. inst = inst->next;
  717. goto Switchstmt;
  718. }
  719. break;
  720. case EOL:
  721. if(p==f->Buffer.nc || filereadc(f, p)=='\n')
  722. goto Step;
  723. break;
  724. case CCLASS:
  725. if(c>=0 && classmatch(inst->rclass, c, 0))
  726. goto Addinst;
  727. break;
  728. case NCCLASS:
  729. if(c>=0 && classmatch(inst->rclass, c, 1))
  730. goto Addinst;
  731. break;
  732. case OR:
  733. /* evaluate right choice later */
  734. if(addinst(tl, inst->right, &tlp->se))
  735. if(++ntl >= NLIST)
  736. goto Overflow;
  737. /* efficiency: advance and re-evaluate */
  738. inst = inst->left;
  739. goto Switchstmt;
  740. case END: /* Match! */
  741. tlp->se.p[0].p1 = -tlp->se.p[0].p1; /* minus sign */
  742. tlp->se.p[0].p2 = p;
  743. bnewmatch(&tlp->se);
  744. break;
  745. }
  746. }
  747. }
  748. Return:
  749. return sel.p[0].p1>=0;
  750. }
  751. void
  752. bnewmatch(Rangeset *sp)
  753. {
  754. int i;
  755. 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))
  756. for(i = 0; i<NSUBEXP; i++){ /* note the reversal; p1<=p2 */
  757. sel.p[i].p1 = sp->p[i].p2;
  758. sel.p[i].p2 = sp->p[i].p1;
  759. }
  760. }