regcore.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:29k
源码类别:

VxWorks

开发平台:

C/C++

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