regexp.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  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 127
  43. Ilist *tl, *nl; /* This list, next list */
  44. Ilist list[2][NLIST+1]; /* +1 for trailing null */
  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. int 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. int
  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 0; /* It's already there */
  499. }
  500. }
  501. p->inst = inst;
  502. p->se= *sep;
  503. (p+1)->inst = 0;
  504. return 1;
  505. }
  506. int
  507. execute(File *f, Posn startp, Posn eof)
  508. {
  509. int flag = 0;
  510. Inst *inst;
  511. Ilist *tlp;
  512. Posn p = startp;
  513. int nnl = 0, ntl;
  514. int c;
  515. int wrapped = 0;
  516. int startchar = startinst->type<OPERATOR? startinst->type : 0;
  517. list[0][0].inst = list[1][0].inst = 0;
  518. sel.p[0].p1 = -1;
  519. /* Execute machine once for each character */
  520. for(;;p++){
  521. doloop:
  522. c = filereadc(f, p);
  523. if(p>=eof || c<0){
  524. switch(wrapped++){
  525. case 0: /* let loop run one more click */
  526. case 2:
  527. break;
  528. case 1: /* expired; wrap to beginning */
  529. if(sel.p[0].p1>=0 || eof!=INFINITY)
  530. goto Return;
  531. list[0][0].inst = list[1][0].inst = 0;
  532. p = 0;
  533. goto doloop;
  534. default:
  535. goto Return;
  536. }
  537. }else if(((wrapped && p>=startp) || sel.p[0].p1>0) && nnl==0)
  538. break;
  539. /* fast check for first char */
  540. if(startchar && nnl==0 && c!=startchar)
  541. continue;
  542. tl = list[flag];
  543. nl = list[flag^=1];
  544. nl->inst = 0;
  545. ntl = nnl;
  546. nnl = 0;
  547. if(sel.p[0].p1<0 && (!wrapped || p<startp || startp==eof)){
  548. /* Add first instruction to this list */
  549. sempty.p[0].p1 = p;
  550. if(addinst(tl, startinst, &sempty))
  551. if(++ntl >= NLIST)
  552. Overflow:
  553. error(Eoverflow);
  554. }
  555. /* Execute machine until this list is empty */
  556. for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment = */
  557. Switchstmt:
  558. switch(inst->type){
  559. default: /* regular character */
  560. if(inst->type==c){
  561. Addinst:
  562. if(addinst(nl, inst->next, &tlp->se))
  563. if(++nnl >= NLIST)
  564. goto Overflow;
  565. }
  566. break;
  567. case LBRA:
  568. if(inst->subid>=0)
  569. tlp->se.p[inst->subid].p1 = p;
  570. inst = inst->next;
  571. goto Switchstmt;
  572. case RBRA:
  573. if(inst->subid>=0)
  574. tlp->se.p[inst->subid].p2 = p;
  575. inst = inst->next;
  576. goto Switchstmt;
  577. case ANY:
  578. if(c!='\n')
  579. goto Addinst;
  580. break;
  581. case BOL:
  582. if(p==0 || filereadc(f, p - 1)=='\n'){
  583. Step:
  584. inst = inst->next;
  585. goto Switchstmt;
  586. }
  587. break;
  588. case EOL:
  589. if(c == '\n')
  590. goto Step;
  591. break;
  592. case CCLASS:
  593. if(c>=0 && classmatch(inst->rclass, c, 0))
  594. goto Addinst;
  595. break;
  596. case NCCLASS:
  597. if(c>=0 && classmatch(inst->rclass, c, 1))
  598. goto Addinst;
  599. break;
  600. case OR:
  601. /* evaluate right choice later */
  602. if(addinst(tlp, inst->right, &tlp->se))
  603. if(++ntl >= NLIST)
  604. goto Overflow;
  605. /* efficiency: advance and re-evaluate */
  606. inst = inst->left;
  607. goto Switchstmt;
  608. case END: /* Match! */
  609. tlp->se.p[0].p2 = p;
  610. newmatch(&tlp->se);
  611. break;
  612. }
  613. }
  614. }
  615. Return:
  616. return sel.p[0].p1>=0;
  617. }
  618. void
  619. newmatch(Rangeset *sp)
  620. {
  621. int i;
  622. if(sel.p[0].p1<0 || sp->p[0].p1<sel.p[0].p1 ||
  623. (sp->p[0].p1==sel.p[0].p1 && sp->p[0].p2>sel.p[0].p2))
  624. for(i = 0; i<NSUBEXP; i++)
  625. sel.p[i] = sp->p[i];
  626. }
  627. int
  628. bexecute(File *f, Posn startp)
  629. {
  630. int flag = 0;
  631. Inst *inst;
  632. Ilist *tlp;
  633. Posn p = startp;
  634. int nnl = 0, ntl;
  635. int c;
  636. int wrapped = 0;
  637. int startchar = bstartinst->type<OPERATOR? bstartinst->type : 0;
  638. list[0][0].inst = list[1][0].inst = 0;
  639. sel.p[0].p1= -1;
  640. /* Execute machine once for each character, including terminal NUL */
  641. for(;;--p){
  642. doloop:
  643. if((c = filereadc(f, p - 1))==-1){
  644. switch(wrapped++){
  645. case 0: /* let loop run one more click */
  646. case 2:
  647. break;
  648. case 1: /* expired; wrap to end */
  649. if(sel.p[0].p1>=0)
  650. case 3:
  651. goto Return;
  652. list[0][0].inst = list[1][0].inst = 0;
  653. p = f->nc;
  654. goto doloop;
  655. default:
  656. goto Return;
  657. }
  658. }else if(((wrapped && p<=startp) || sel.p[0].p1>0) && nnl==0)
  659. break;
  660. /* fast check for first char */
  661. if(startchar && nnl==0 && c!=startchar)
  662. continue;
  663. tl = list[flag];
  664. nl = list[flag^=1];
  665. nl->inst = 0;
  666. ntl = nnl;
  667. nnl = 0;
  668. if(sel.p[0].p1<0 && (!wrapped || p>startp)){
  669. /* Add first instruction to this list */
  670. /* the minus is so the optimizations in addinst work */
  671. sempty.p[0].p1 = -p;
  672. if(addinst(tl, bstartinst, &sempty))
  673. if(++ntl >= NLIST)
  674. Overflow:
  675. error(Eoverflow);
  676. }
  677. /* Execute machine until this list is empty */
  678. for(tlp = tl; inst = tlp->inst; tlp++){ /* assignment = */
  679. Switchstmt:
  680. switch(inst->type){
  681. default: /* regular character */
  682. if(inst->type == c){
  683. Addinst:
  684. if(addinst(nl, inst->next, &tlp->se))
  685. if(++nnl >= NLIST)
  686. goto Overflow;
  687. }
  688. break;
  689. case LBRA:
  690. if(inst->subid>=0)
  691. tlp->se.p[inst->subid].p1 = p;
  692. inst = inst->next;
  693. goto Switchstmt;
  694. case RBRA:
  695. if(inst->subid >= 0)
  696. tlp->se.p[inst->subid].p2 = p;
  697. inst = inst->next;
  698. goto Switchstmt;
  699. case ANY:
  700. if(c != '\n')
  701. goto Addinst;
  702. break;
  703. case BOL:
  704. if(c=='\n' || p==0){
  705. Step:
  706. inst = inst->next;
  707. goto Switchstmt;
  708. }
  709. break;
  710. case EOL:
  711. if(p==f->nc || filereadc(f, p)=='\n')
  712. goto Step;
  713. break;
  714. case CCLASS:
  715. if(c>=0 && classmatch(inst->rclass, c, 0))
  716. goto Addinst;
  717. break;
  718. case NCCLASS:
  719. if(c>=0 && classmatch(inst->rclass, c, 1))
  720. goto Addinst;
  721. break;
  722. case OR:
  723. /* evaluate right choice later */
  724. if(addinst(tl, inst->right, &tlp->se))
  725. if(++ntl >= NLIST)
  726. goto Overflow;
  727. /* efficiency: advance and re-evaluate */
  728. inst = inst->left;
  729. goto Switchstmt;
  730. case END: /* Match! */
  731. tlp->se.p[0].p1 = -tlp->se.p[0].p1; /* minus sign */
  732. tlp->se.p[0].p2 = p;
  733. bnewmatch(&tlp->se);
  734. break;
  735. }
  736. }
  737. }
  738. Return:
  739. return sel.p[0].p1>=0;
  740. }
  741. void
  742. bnewmatch(Rangeset *sp)
  743. {
  744. int i;
  745. 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))
  746. for(i = 0; i<NSUBEXP; i++){ /* note the reversal; p1<=p2 */
  747. sel.p[i].p1 = sp->p[i].p2;
  748. sel.p[i].p2 = sp->p[i].p1;
  749. }
  750. }