engine.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:29k
源码类别:

数据库系统

开发平台:

Unix_Linux

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