regexp.c 15 KB

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