engine.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:25k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * The matching engine and friends.  This file is #included by regexec.c
  3.  * after suitable #defines of a variety of macros used herein, so that
  4.  * different state representations can be used without duplicating masses
  5.  * of code.
  6.  */
  7. #ifdef SNAMES
  8. #define matcher smatcher
  9. #define fast sfast
  10. #define slow sslow
  11. #define dissect sdissect
  12. #define backref sbackref
  13. #define step sstep
  14. #define print sprint
  15. #define at sat
  16. #define match smat
  17. #endif
  18. #ifdef LNAMES
  19. #define matcher lmatcher
  20. #define fast lfast
  21. #define slow lslow
  22. #define dissect ldissect
  23. #define backref lbackref
  24. #define step lstep
  25. #define print lprint
  26. #define at lat
  27. #define match lmat
  28. #endif
  29. /* another structure passed up and down to avoid zillions of parameters */
  30. struct match {
  31. struct re_guts *g;
  32. int eflags;
  33. regmatch_t *pmatch; /* [nsub+1] (0 element unused) */
  34. char *offp; /* offsets work from here */
  35. char *beginp; /* start of string -- virtual NUL precedes */
  36. char *endp; /* end of string -- virtual NUL here */
  37. char *coldp; /* can be no match starting before here */
  38. char **lastpos; /* [nplus+1] */
  39. STATEVARS;
  40. states st; /* current states */
  41. states fresh; /* states for a fresh start */
  42. states tmp; /* temporary */
  43. states empty; /* empty set of states */
  44. };
  45. #include "engine.ih"
  46. #ifdef REDEBUG
  47. #define SP(t, s, c) print(m, t, s, c, stdout)
  48. #define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2)
  49. #define NOTE(str) { if (m->eflags&REG_TRACE) printf("=%sn", (str)); }
  50. #else
  51. #define SP(t, s, c) /* nothing */
  52. #define AT(t, p1, p2, s1, s2) /* nothing */
  53. #define NOTE(s) /* nothing */
  54. #endif
  55. /*
  56.  - matcher - the actual matching engine
  57.  == static int matcher(register struct re_guts *g, char *string, 
  58.  == size_t nmatch, regmatch_t pmatch[], int eflags);
  59.  */
  60. static int /* 0 success, REG_NOMATCH failure */
  61. matcher(g, str, nmatch, pmatch, eflags)
  62. register struct re_guts *g;
  63. char *str;
  64. size_t nmatch;
  65. regmatch_t pmatch[];
  66. int eflags;
  67. {
  68. register char *endp;
  69. register uint i;
  70. struct match mv;
  71. register struct match *m = &mv;
  72. register char *dp;
  73. register const sopno gf = g->firststate+1; /* +1 for OEND */
  74. register const sopno gl = g->laststate;
  75. char *start;
  76. char *stop;
  77. /* simplify the situation where possible */
  78. if (g->cflags&REG_NOSUB)
  79. nmatch = 0;
  80. if (eflags&REG_STARTEND) {
  81. start = str + pmatch[0].rm_so;
  82. stop = str + pmatch[0].rm_eo;
  83. } else {
  84. start = str;
  85. stop = start + strlen(start);
  86. }
  87. if (stop < start)
  88. return(REG_INVARG);
  89. /* prescreening; this does wonders for this rather slow code */
  90. if (g->must != NULL) {
  91. for (dp = start; dp < stop; dp++)
  92. if (*dp == g->must[0] && stop - dp >= g->mlen &&
  93. memcmp(dp, g->must, (size_t)g->mlen) == 0)
  94. break;
  95. if (dp == stop) /* we didn't find g->must */
  96. return(REG_NOMATCH);
  97. }
  98. /* match struct setup */
  99. m->g = g;
  100. m->eflags = eflags;
  101. m->pmatch = NULL;
  102. m->lastpos = NULL;
  103. m->offp = str;
  104. m->beginp = start;
  105. m->endp = stop;
  106. STATESETUP(m, 4);
  107. SETUP(m->st);
  108. SETUP(m->fresh);
  109. SETUP(m->tmp);
  110. SETUP(m->empty);
  111. CLEAR(m->empty);
  112. /* this loop does only one repetition except for backrefs */
  113. for (;;) {
  114. endp = fast(m, start, stop, gf, gl);
  115. if (endp == NULL) { /* a miss */
  116.   if (m->pmatch != NULL)
  117.     free((char *)m->pmatch);
  118.   if (m->lastpos != NULL)
  119.     free((char *)m->lastpos);
  120.   STATETEARDOWN(m);
  121.   return(REG_NOMATCH);
  122. }
  123. if (nmatch == 0 && !g->backrefs)
  124. break; /* no further info needed */
  125. /* where? */
  126. assert(m->coldp != NULL);
  127. for (;;) {
  128. NOTE("finding start");
  129. endp = slow(m, m->coldp, stop, gf, gl);
  130. if (endp != NULL)
  131. break;
  132. assert(m->coldp < m->endp);
  133. m->coldp++;
  134. }
  135. if (nmatch == 1 && !g->backrefs)
  136. break; /* no further info needed */
  137. /* oh my, he wants the subexpressions... */
  138. if (m->pmatch == NULL)
  139. m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) *
  140. sizeof(regmatch_t));
  141. if (m->pmatch == NULL) {
  142.    if (m->lastpos != NULL)
  143.      free((char *)m->lastpos);
  144. STATETEARDOWN(m);
  145. return(REG_ESPACE);
  146. }
  147. for (i = 1; i <= m->g->nsub; i++)
  148. m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;
  149. if (!g->backrefs && !(m->eflags&REG_BACKR)) {
  150. NOTE("dissecting");
  151. dp = dissect(m, m->coldp, endp, gf, gl);
  152. } else {
  153. if (g->nplus > 0 && m->lastpos == NULL)
  154. m->lastpos = (char **)malloc((g->nplus+1) *
  155. sizeof(char *));
  156. if (g->nplus > 0 && m->lastpos == NULL) {
  157. free(m->pmatch);
  158. STATETEARDOWN(m);
  159. return(REG_ESPACE);
  160. }
  161. NOTE("backref dissect");
  162. dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
  163. }
  164. if (dp != NULL)
  165. break;
  166. /* uh-oh... we couldn't find a subexpression-level match */
  167. assert(g->backrefs); /* must be back references doing it */
  168. assert(g->nplus == 0 || m->lastpos != NULL);
  169. for (;;) {
  170. if (dp != NULL || endp <= m->coldp)
  171. break; /* defeat */
  172. NOTE("backoff");
  173. endp = slow(m, m->coldp, endp-1, gf, gl);
  174. if (endp == NULL)
  175. break; /* defeat */
  176. /* try it on a shorter possibility */
  177. #ifndef NDEBUG
  178. for (i = 1; i <= m->g->nsub; i++) {
  179. assert(m->pmatch[i].rm_so == -1);
  180. assert(m->pmatch[i].rm_eo == -1);
  181. }
  182. #endif
  183. NOTE("backoff dissect");
  184. dp = backref(m, m->coldp, endp, gf, gl, (sopno)0);
  185. }
  186. assert(dp == NULL || dp == endp);
  187. if (dp != NULL) /* found a shorter one */
  188. break;
  189. /* despite initial appearances, there is no match here */
  190. NOTE("false alarm");
  191. start = m->coldp + 1; /* recycle starting later */
  192. assert(start <= stop);
  193. }
  194. /* fill in the details if requested */
  195. if (nmatch > 0) {
  196. pmatch[0].rm_so = m->coldp - m->offp;
  197. pmatch[0].rm_eo = endp - m->offp;
  198. }
  199. if (nmatch > 1) {
  200. assert(m->pmatch != NULL);
  201. for (i = 1; i < nmatch; i++)
  202. if (i <= m->g->nsub)
  203. pmatch[i] = m->pmatch[i];
  204. else {
  205. pmatch[i].rm_so = -1;
  206. pmatch[i].rm_eo = -1;
  207. }
  208. }
  209. if (m->pmatch != NULL)
  210. free((char *)m->pmatch);
  211. if (m->lastpos != NULL)
  212. free((char *)m->lastpos);
  213. STATETEARDOWN(m);
  214. return(0);
  215. }
  216. /*
  217.  - dissect - figure out what matched what, no back references
  218.  == static char *dissect(register struct match *m, char *start, 
  219.  == char *stop, sopno startst, sopno stopst);
  220.  */
  221. static char * /* == stop (success) always */
  222. dissect(m, start, stop, startst, stopst)
  223. register struct match *m;
  224. char *start;
  225. char *stop;
  226. sopno startst;
  227. sopno stopst;
  228. {
  229. register uint i;
  230. register sopno ss; /* start sop of current subRE */
  231. register sopno es; /* end sop of current subRE */
  232. register char *sp; /* start of string matched by it */
  233. register char *stp; /* string matched by it cannot pass here */
  234. register char *rest; /* start of rest of string */
  235. register char *tail; /* string unmatched by rest of RE */
  236. register sopno ssub; /* start sop of subsubRE */
  237. register sopno esub; /* end sop of subsubRE */
  238. register char *ssp; /* start of string matched by subsubRE */
  239. register char *sep; /* end of string matched by subsubRE */
  240. register char *oldssp; /* previous ssp */
  241. register char *dp;
  242. AT("diss", start, stop, startst, stopst);
  243. sp = start;
  244. for (ss = startst; ss < stopst; ss = es) {
  245. /* identify end of subRE */
  246. es = ss;
  247. switch (OP(m->g->strip[es])) {
  248. case OPLUS_:
  249. case OQUEST_:
  250. es += OPND(m->g->strip[es]);
  251. break;
  252. case OCH_:
  253. while (OP(m->g->strip[es]) != O_CH)
  254. es += OPND(m->g->strip[es]);
  255. break;
  256. }
  257. es++;
  258. /* figure out what it matched */
  259. switch (OP(m->g->strip[ss])) {
  260. case OEND:
  261. assert(nope);
  262. break;
  263. case OCHAR:
  264. sp++;
  265. break;
  266. case OBOL:
  267. case OEOL:
  268. case OBOW:
  269. case OEOW:
  270. break;
  271. case OANY:
  272. case OANYOF:
  273. sp++;
  274. break;
  275. case OBACK_:
  276. case O_BACK:
  277. assert(nope);
  278. break;
  279. /* cases where length of match is hard to find */
  280. case OQUEST_:
  281. stp = stop;
  282. for (;;) {
  283. /* how long could this one be? */
  284. rest = slow(m, sp, stp, ss, es);
  285. assert(rest != NULL); /* it did match */
  286. /* could the rest match the rest? */
  287. tail = slow(m, rest, stop, es, stopst);
  288. if (tail == stop)
  289. break; /* yes! */
  290. /* no -- try a shorter match for this one */
  291. stp = rest - 1;
  292. assert(stp >= sp); /* it did work */
  293. }
  294. ssub = ss + 1;
  295. esub = es - 1;
  296. /* did innards match? */
  297. if (slow(m, sp, rest, ssub, esub) != NULL) {
  298. dp = dissect(m, sp, rest, ssub, esub);
  299. assert(dp == rest);
  300. } else /* no */
  301. assert(sp == rest);
  302. sp = rest;
  303. break;
  304. case OPLUS_:
  305. stp = stop;
  306. for (;;) {
  307. /* how long could this one be? */
  308. rest = slow(m, sp, stp, ss, es);
  309. assert(rest != NULL); /* it did match */
  310. /* could the rest match the rest? */
  311. tail = slow(m, rest, stop, es, stopst);
  312. if (tail == stop)
  313. break; /* yes! */
  314. /* no -- try a shorter match for this one */
  315. stp = rest - 1;
  316. assert(stp >= sp); /* it did work */
  317. }
  318. ssub = ss + 1;
  319. esub = es - 1;
  320. ssp = sp;
  321. oldssp = ssp;
  322. for (;;) { /* find last match of innards */
  323. sep = slow(m, ssp, rest, ssub, esub);
  324. if (sep == NULL || sep == ssp)
  325. break; /* failed or matched null */
  326. oldssp = ssp; /* on to next try */
  327. ssp = sep;
  328. }
  329. if (sep == NULL) {
  330. /* last successful match */
  331. sep = ssp;
  332. ssp = oldssp;
  333. }
  334. assert(sep == rest); /* must exhaust substring */
  335. assert(slow(m, ssp, sep, ssub, esub) == rest);
  336. dp = dissect(m, ssp, sep, ssub, esub);
  337. assert(dp == sep);
  338. sp = rest;
  339. break;
  340. case OCH_:
  341. stp = stop;
  342. for (;;) {
  343. /* how long could this one be? */
  344. rest = slow(m, sp, stp, ss, es);
  345. assert(rest != NULL); /* it did match */
  346. /* could the rest match the rest? */
  347. tail = slow(m, rest, stop, es, stopst);
  348. if (tail == stop)
  349. break; /* yes! */
  350. /* no -- try a shorter match for this one */
  351. stp = rest - 1;
  352. assert(stp >= sp); /* it did work */
  353. }
  354. ssub = ss + 1;
  355. esub = ss + OPND(m->g->strip[ss]) - 1;
  356. assert(OP(m->g->strip[esub]) == OOR1);
  357. for (;;) { /* find first matching branch */
  358. if (slow(m, sp, rest, ssub, esub) == rest)
  359. break; /* it matched all of it */
  360. /* that one missed, try next one */
  361. assert(OP(m->g->strip[esub]) == OOR1);
  362. esub++;
  363. assert(OP(m->g->strip[esub]) == OOR2);
  364. ssub = esub + 1;
  365. esub += OPND(m->g->strip[esub]);
  366. if (OP(m->g->strip[esub]) == OOR2)
  367. esub--;
  368. else
  369. assert(OP(m->g->strip[esub]) == O_CH);
  370. }
  371. dp = dissect(m, sp, rest, ssub, esub);
  372. assert(dp == rest);
  373. sp = rest;
  374. break;
  375. case O_PLUS:
  376. case O_QUEST:
  377. case OOR1:
  378. case OOR2:
  379. case O_CH:
  380. assert(nope);
  381. break;
  382. case OLPAREN:
  383. i = OPND(m->g->strip[ss]);
  384. assert(0 < i && i <= m->g->nsub);
  385. m->pmatch[i].rm_so = sp - m->offp;
  386. break;
  387. case ORPAREN:
  388. i = OPND(m->g->strip[ss]);
  389. assert(0 < i && i <= m->g->nsub);
  390. m->pmatch[i].rm_eo = sp - m->offp;
  391. break;
  392. default: /* uh oh */
  393. assert(nope);
  394. break;
  395. }
  396. }
  397. assert(sp == stop);
  398. return(sp);
  399. }
  400. /*
  401.  - backref - figure out what matched what, figuring in back references
  402.  == static char *backref(register struct match *m, char *start, 
  403.  == char *stop, sopno startst, sopno stopst, sopno lev);
  404.  */
  405. static char * /* == stop (success) or NULL (failure) */
  406. backref(m, start, stop, startst, stopst, lev)
  407. register struct match *m;
  408. char *start;
  409. char *stop;
  410. sopno startst;
  411. sopno stopst;
  412. sopno lev; /* PLUS nesting level */
  413. {
  414. register uint i;
  415. register sopno ss; /* start sop of current subRE */
  416. register char *sp; /* start of string matched by it */
  417. register sopno ssub; /* start sop of subsubRE */
  418. register sopno esub; /* end sop of subsubRE */
  419. register char *ssp; /* start of string matched by subsubRE */
  420. register char *dp;
  421. register size_t len;
  422. register int hard;
  423. register sop s;
  424. register regoff_t offsave;
  425. register cset *cs;
  426. AT("back", start, stop, startst, stopst);
  427. sp = start;
  428. /* get as far as we can with easy stuff */
  429. hard = 0;
  430. for (ss = startst; !hard && ss < stopst; ss++)
  431. switch (OP(s = m->g->strip[ss])) {
  432. case OCHAR:
  433. if (sp == stop || *sp++ != (char)OPND(s))
  434. return(NULL);
  435. break;
  436. case OANY:
  437. if (sp == stop)
  438. return(NULL);
  439. sp++;
  440. break;
  441. case OANYOF:
  442. cs = &m->g->sets[OPND(s)];
  443. if (sp == stop || !CHIN(cs, *sp++))
  444. return(NULL);
  445. break;
  446. case OBOL:
  447. if ( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
  448. (sp < m->endp && *(sp-1) == 'n' &&
  449. (m->g->cflags&REG_NEWLINE)) )
  450. { /* yes */ }
  451. else
  452. return(NULL);
  453. break;
  454. case OEOL:
  455. if ( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
  456. (sp < m->endp && *sp == 'n' &&
  457. (m->g->cflags&REG_NEWLINE)) )
  458. { /* yes */ }
  459. else
  460. return(NULL);
  461. break;
  462. case OBOW:
  463. if (( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
  464. (sp < m->endp && *(sp-1) == 'n' &&
  465. (m->g->cflags&REG_NEWLINE)) ||
  466. (sp > m->beginp &&
  467. !ISWORD(*(sp-1))) ) &&
  468. (sp < m->endp && ISWORD(*sp)) )
  469. { /* yes */ }
  470. else
  471. return(NULL);
  472. break;
  473. case OEOW:
  474. if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
  475. (sp < m->endp && *sp == 'n' &&
  476. (m->g->cflags&REG_NEWLINE)) ||
  477. (sp < m->endp && !ISWORD(*sp)) ) &&
  478. (sp > m->beginp && ISWORD(*(sp-1))) )
  479. { /* yes */ }
  480. else
  481. return(NULL);
  482. break;
  483. case O_QUEST:
  484. break;
  485. case OOR1: /* matches null but needs to skip */
  486. ss++;
  487. s = m->g->strip[ss];
  488. do {
  489. assert(OP(s) == OOR2);
  490. ss += OPND(s);
  491. } while (OP(s = m->g->strip[ss]) != O_CH);
  492. /* note that the ss++ gets us past the O_CH */
  493. break;
  494. default: /* have to make a choice */
  495. hard = 1;
  496. break;
  497. }
  498. if (!hard) { /* that was it! */
  499. if (sp != stop)
  500. return(NULL);
  501. return(sp);
  502. }
  503. ss--; /* adjust for the for's final increment */
  504. /* the hard stuff */
  505. AT("hard", sp, stop, ss, stopst);
  506. s = m->g->strip[ss];
  507. switch (OP(s)) {
  508. case OBACK_: /* the vilest depths */
  509. i = OPND(s);
  510. assert(0 < i && i <= m->g->nsub);
  511. if (m->pmatch[i].rm_eo == -1)
  512. return(NULL);
  513. assert(m->pmatch[i].rm_so != -1);
  514. len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
  515. assert((size_t) (stop - m->beginp) >= len);
  516. if (sp > stop - len)
  517. return(NULL); /* not enough left to match */
  518. ssp = m->offp + m->pmatch[i].rm_so;
  519. if (memcmp(sp, ssp, len) != 0)
  520. return(NULL);
  521. while (m->g->strip[ss] != SOP(O_BACK, i))
  522. ss++;
  523. return(backref(m, sp+len, stop, ss+1, stopst, lev));
  524. break;
  525. case OQUEST_: /* to null or not */
  526. dp = backref(m, sp, stop, ss+1, stopst, lev);
  527. if (dp != NULL)
  528. return(dp); /* not */
  529. return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev));
  530. break;
  531. case OPLUS_:
  532. assert(m->lastpos != NULL);
  533. assert(lev+1 <= m->g->nplus);
  534. m->lastpos[lev+1] = sp;
  535. return(backref(m, sp, stop, ss+1, stopst, lev+1));
  536. break;
  537. case O_PLUS:
  538. if (sp == m->lastpos[lev]) /* last pass matched null */
  539. return(backref(m, sp, stop, ss+1, stopst, lev-1));
  540. /* try another pass */
  541. m->lastpos[lev] = sp;
  542. dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev);
  543. if (dp == NULL)
  544. return(backref(m, sp, stop, ss+1, stopst, lev-1));
  545. else
  546. return(dp);
  547. break;
  548. case OCH_: /* find the right one, if any */
  549. ssub = ss + 1;
  550. esub = ss + OPND(s) - 1;
  551. assert(OP(m->g->strip[esub]) == OOR1);
  552. for (;;) { /* find first matching branch */
  553. dp = backref(m, sp, stop, ssub, esub, lev);
  554. if (dp != NULL)
  555. return(dp);
  556. /* that one missed, try next one */
  557. if (OP(m->g->strip[esub]) == O_CH)
  558. return(NULL); /* there is none */
  559. esub++;
  560. assert(OP(m->g->strip[esub]) == OOR2);
  561. ssub = esub + 1;
  562. esub += OPND(m->g->strip[esub]);
  563. if (OP(m->g->strip[esub]) == OOR2)
  564. esub--;
  565. else
  566. assert(OP(m->g->strip[esub]) == O_CH);
  567. }
  568. break;
  569. case OLPAREN: /* must undo assignment if rest fails */
  570. i = OPND(s);
  571. assert(0 < i && i <= m->g->nsub);
  572. offsave = m->pmatch[i].rm_so;
  573. m->pmatch[i].rm_so = sp - m->offp;
  574. dp = backref(m, sp, stop, ss+1, stopst, lev);
  575. if (dp != NULL)
  576. return(dp);
  577. m->pmatch[i].rm_so = offsave;
  578. return(NULL);
  579. break;
  580. case ORPAREN: /* must undo assignment if rest fails */
  581. i = OPND(s);
  582. assert(0 < i && i <= m->g->nsub);
  583. offsave = m->pmatch[i].rm_eo;
  584. m->pmatch[i].rm_eo = sp - m->offp;
  585. dp = backref(m, sp, stop, ss+1, stopst, lev);
  586. if (dp != NULL)
  587. return(dp);
  588. m->pmatch[i].rm_eo = offsave;
  589. return(NULL);
  590. break;
  591. default: /* uh oh */
  592. assert(nope);
  593. break;
  594. }
  595. /* "can't happen" */
  596. assert(nope);
  597. /* NOTREACHED */
  598. return 0; /* Keep gcc happy */
  599. }
  600. /*
  601.  - fast - step through the string at top speed
  602.  == static char *fast(register struct match *m, char *start, 
  603.  == char *stop, sopno startst, sopno stopst);
  604.  */
  605. static char * /* where tentative match ended, or NULL */
  606. fast(m, start, stop, startst, stopst)
  607. register struct match *m;
  608. char *start;
  609. char *stop;
  610. sopno startst;
  611. sopno stopst;
  612. {
  613. register states st = m->st;
  614. register states fresh = m->fresh;
  615. register states tmp = m->tmp;
  616. register char *p = start;
  617. register int c = (start == m->beginp) ? OUT : *(start-1);
  618. register int lastc; /* previous c */
  619. register int flagch;
  620. register int i;
  621. register char *coldp; /* last p after which no match was underway */
  622. CLEAR(st);
  623. SET1(st, startst);
  624. st = step(m->g, startst, stopst, st, NOTHING, st);
  625. ASSIGN(fresh, st);
  626. SP("start", st, *p);
  627. coldp = NULL;
  628. for (;;) {
  629. /* next character */
  630. lastc = c;
  631. c = (p == m->endp) ? OUT : *p;
  632. if (EQ(st, fresh))
  633. coldp = p;
  634. /* is there an EOL and/or BOL between lastc and c? */
  635. flagch = '';
  636. i = 0;
  637. if ( (lastc == 'n' && m->g->cflags&REG_NEWLINE) ||
  638. (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
  639. flagch = BOL;
  640. i = m->g->nbol;
  641. }
  642. if ( (c == 'n' && m->g->cflags&REG_NEWLINE) ||
  643. (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
  644. flagch = (flagch == BOL) ? BOLEOL : EOL;
  645. i += m->g->neol;
  646. }
  647. if (i != 0) {
  648. for (; i > 0; i--)
  649. st = step(m->g, startst, stopst, st, flagch, st);
  650. SP("boleol", st, c);
  651. }
  652. /* how about a word boundary? */
  653. if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
  654. (c != OUT && ISWORD(c)) ) {
  655. flagch = BOW;
  656. }
  657. if ( (lastc != OUT && ISWORD(lastc)) &&
  658. (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
  659. flagch = EOW;
  660. }
  661. if (flagch == BOW || flagch == EOW) {
  662. st = step(m->g, startst, stopst, st, flagch, st);
  663. SP("boweow", st, c);
  664. }
  665. /* are we done? */
  666. if (ISSET(st, stopst) || p == stop)
  667. break; /* NOTE BREAK OUT */
  668. /* no, we must deal with this character */
  669. ASSIGN(tmp, st);
  670. ASSIGN(st, fresh);
  671. assert(c != OUT);
  672. st = step(m->g, startst, stopst, tmp, c, st);
  673. SP("aft", st, c);
  674. assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
  675. p++;
  676. }
  677. assert(coldp != NULL);
  678. m->coldp = coldp;
  679. if (ISSET(st, stopst))
  680. return(p+1);
  681. else
  682. return(NULL);
  683. }
  684. /*
  685.  - slow - step through the string more deliberately
  686.  == static char *slow(register struct match *m, char *start, 
  687.  == char *stop, sopno startst, sopno stopst);
  688.  */
  689. static char * /* where it ended */
  690. slow(m, start, stop, startst, stopst)
  691. register struct match *m;
  692. char *start;
  693. char *stop;
  694. sopno startst;
  695. sopno stopst;
  696. {
  697. register states st = m->st;
  698. register states empty = m->empty;
  699. register states tmp = m->tmp;
  700. register char *p = start;
  701. register int c = (start == m->beginp) ? OUT : *(start-1);
  702. register int lastc; /* previous c */
  703. register int flagch;
  704. register int i;
  705. register char *matchp; /* last p at which a match ended */
  706. AT("slow", start, stop, startst, stopst);
  707. CLEAR(st);
  708. SET1(st, startst);
  709. SP("sstart", st, *p);
  710. st = step(m->g, startst, stopst, st, NOTHING, st);
  711. matchp = NULL;
  712. for (;;) {
  713. /* next character */
  714. lastc = c;
  715. c = (p == m->endp) ? OUT : *p;
  716. /* is there an EOL and/or BOL between lastc and c? */
  717. flagch = '';
  718. i = 0;
  719. if ( (lastc == 'n' && m->g->cflags&REG_NEWLINE) ||
  720. (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
  721. flagch = BOL;
  722. i = m->g->nbol;
  723. }
  724. if ( (c == 'n' && m->g->cflags&REG_NEWLINE) ||
  725. (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
  726. flagch = (flagch == BOL) ? BOLEOL : EOL;
  727. i += m->g->neol;
  728. }
  729. if (i != 0) {
  730. for (; i > 0; i--)
  731. st = step(m->g, startst, stopst, st, flagch, st);
  732. SP("sboleol", st, c);
  733. }
  734. /* how about a word boundary? */
  735. if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
  736. (c != OUT && ISWORD(c)) ) {
  737. flagch = BOW;
  738. }
  739. if ( (lastc != OUT && ISWORD(lastc)) &&
  740. (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
  741. flagch = EOW;
  742. }
  743. if (flagch == BOW || flagch == EOW) {
  744. st = step(m->g, startst, stopst, st, flagch, st);
  745. SP("sboweow", st, c);
  746. }
  747. /* are we done? */
  748. if (ISSET(st, stopst))
  749. matchp = p;
  750. if (EQ(st, empty) || p == stop)
  751. break; /* NOTE BREAK OUT */
  752. /* no, we must deal with this character */
  753. ASSIGN(tmp, st);
  754. ASSIGN(st, empty);
  755. assert(c != OUT);
  756. st = step(m->g, startst, stopst, tmp, c, st);
  757. SP("saft", st, c);
  758. assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
  759. p++;
  760. }
  761. return(matchp);
  762. }
  763. /*
  764.  - step - map set of states reachable before char to set reachable after
  765.  == static states step(register struct re_guts *g, sopno start, sopno stop, 
  766.  == register states bef, int ch, register states aft);
  767.  == #define BOL (OUT+1)
  768.  == #define EOL (BOL+1)
  769.  == #define BOLEOL (BOL+2)
  770.  == #define NOTHING (BOL+3)
  771.  == #define BOW (BOL+4)
  772.  == #define EOW (BOL+5)
  773.  == #define CODEMAX (BOL+5) // highest code used
  774.  == #define NONCHAR(c) ((c) > CHAR_MAX)
  775.  == #define NNONCHAR (CODEMAX-CHAR_MAX)
  776.  */
  777. static states
  778. step(g, start, stop, bef, ch, aft)
  779. register struct re_guts *g;
  780. sopno start; /* start state within strip */
  781. sopno stop; /* state after stop state within strip */
  782. register states bef; /* states reachable before */
  783. int ch; /* character or NONCHAR code */
  784. register states aft; /* states already known reachable after */
  785. {
  786. register cset *cs;
  787. register sop s;
  788. register sopno pc;
  789. register onestate here; /* note, macros know this name */
  790. register sopno look;
  791. register int i;
  792. for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {
  793. s = g->strip[pc];
  794. switch (OP(s)) {
  795. case OEND:
  796. assert(pc == stop-1);
  797. break;
  798. case OCHAR:
  799. /* only characters can match */
  800. assert(!NONCHAR(ch) || ch != (char)OPND(s));
  801. if (ch == (char)OPND(s))
  802. FWD(aft, bef, 1);
  803. break;
  804. case OBOL:
  805. if (ch == BOL || ch == BOLEOL)
  806. FWD(aft, bef, 1);
  807. break;
  808. case OEOL:
  809. if (ch == EOL || ch == BOLEOL)
  810. FWD(aft, bef, 1);
  811. break;
  812. case OBOW:
  813. if (ch == BOW)
  814. FWD(aft, bef, 1);
  815. break;
  816. case OEOW:
  817. if (ch == EOW)
  818. FWD(aft, bef, 1);
  819. break;
  820. case OANY:
  821. if (!NONCHAR(ch))
  822. FWD(aft, bef, 1);
  823. break;
  824. case OANYOF:
  825. cs = &g->sets[OPND(s)];
  826. if (!NONCHAR(ch) && CHIN(cs, ch))
  827. FWD(aft, bef, 1);
  828. break;
  829. case OBACK_: /* ignored here */
  830. case O_BACK:
  831. FWD(aft, aft, 1);
  832. break;
  833. case OPLUS_: /* forward, this is just an empty */
  834. FWD(aft, aft, 1);
  835. break;
  836. case O_PLUS: /* both forward and back */
  837. FWD(aft, aft, 1);
  838. i = ISSETBACK(aft, OPND(s));
  839. BACK(aft, aft, OPND(s));
  840. if (!i && ISSETBACK(aft, OPND(s))) {
  841. /* oho, must reconsider loop body */
  842. pc -= OPND(s) + 1;
  843. INIT(here, pc);
  844. }
  845. break;
  846. case OQUEST_: /* two branches, both forward */
  847. FWD(aft, aft, 1);
  848. FWD(aft, aft, OPND(s));
  849. break;
  850. case O_QUEST: /* just an empty */
  851. FWD(aft, aft, 1);
  852. break;
  853. case OLPAREN: /* not significant here */
  854. case ORPAREN:
  855. FWD(aft, aft, 1);
  856. break;
  857. case OCH_: /* mark the first two branches */
  858. FWD(aft, aft, 1);
  859. assert(OP(g->strip[pc+OPND(s)]) == OOR2);
  860. FWD(aft, aft, OPND(s));
  861. break;
  862. case OOR1: /* done a branch, find the O_CH */
  863. if (ISSTATEIN(aft, here)) {
  864. for (look = 1;
  865. OP(s = g->strip[pc+look]) != O_CH;
  866. look += OPND(s))
  867. assert(OP(s) == OOR2);
  868. FWD(aft, aft, look);
  869. }
  870. break;
  871. case OOR2: /* propagate OCH_'s marking */
  872. FWD(aft, aft, 1);
  873. if (OP(g->strip[pc+OPND(s)]) != O_CH) {
  874. assert(OP(g->strip[pc+OPND(s)]) == OOR2);
  875. FWD(aft, aft, OPND(s));
  876. }
  877. break;
  878. case O_CH: /* just empty */
  879. FWD(aft, aft, 1);
  880. break;
  881. default: /* ooooops... */
  882. assert(nope);
  883. break;
  884. }
  885. }
  886. return(aft);
  887. }
  888. #ifdef REDEBUG
  889. /*
  890.  - print - print a set of states
  891.  == #ifdef REDEBUG
  892.  == static void print(struct match *m, char *caption, states st, 
  893.  == int ch, FILE *d);
  894.  == #endif
  895.  */
  896. static void
  897. print(m, caption, st, ch, d)
  898. struct match *m;
  899. char *caption;
  900. states st;
  901. int ch;
  902. FILE *d;
  903. {
  904. register struct re_guts *g = m->g;
  905. register int i;
  906. register int first = 1;
  907. char buf[10];
  908. if (!(m->eflags&REG_TRACE))
  909. return;
  910. fprintf(d, "%s", caption);
  911. if (ch != '')
  912. fprintf(d, " %s", printchar(ch,buf));
  913. for (i = 0; i < g->nstates; i++)
  914. if (ISSET(st, i)) {
  915. fprintf(d, "%s%d", (first) ? "t" : ", ", i);
  916. first = 0;
  917. }
  918. fprintf(d, "n");
  919. }
  920. /*
  921.  - at - print current situation
  922.  == #ifdef REDEBUG
  923.  == static void at(struct match *m, char *title, char *start, char *stop, 
  924.  == sopno startst, sopno stopst);
  925.  == #endif
  926.  */
  927. static void
  928. at(m, title, start, stop, startst, stopst)
  929. struct match *m;
  930. char *title;
  931. char *start;
  932. char *stop;
  933. sopno startst;
  934. sopno stopst;
  935. {
  936. char buf[10];
  937. if (!(m->eflags&REG_TRACE))
  938. return;
  939. printf("%s %s-", title, printchar(*start,buf));
  940. printf("%s ", printchar(*stop,buf));
  941. printf("%ld-%ldn", (long)startst, (long)stopst,buf);
  942. }
  943. #ifndef PCHARDONE
  944. #define PCHARDONE /* never again */
  945. /*
  946.  - printchar - make a character printable
  947.  == #ifdef REDEBUG
  948.  == static char *printchar(int ch);
  949.  == #endif
  950.  *
  951.  * Is this identical to regchar() over in debug.c?  Well, yes.  But a
  952.  * duplicate here avoids having a debugging-capable regexec.o tied to
  953.  * a matching debug.o, and this is convenient.  It all disappears in
  954.  * the non-debug compilation anyway, so it doesn't matter much.
  955.  */
  956. static char * /* -> representation */
  957. printchar(ch,pbuf)
  958. int ch;
  959. char *pbuf;
  960. {
  961. if (isprint(ch) || ch == ' ')
  962. sprintf(pbuf, "%c", ch);
  963. else
  964. sprintf(pbuf, "\%o", ch);
  965. return(pbuf);
  966. }
  967. #endif
  968. #endif
  969. #undef matcher
  970. #undef fast
  971. #undef slow
  972. #undef dissect
  973. #undef backref
  974. #undef step
  975. #undef print
  976. #undef at
  977. #undef match