regc_nfa.c
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:38k
源码类别:

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * NFA utilities.
  3.  * This file is #included by regcomp.c.
  4.  *
  5.  * Copyright (c) 1998, 1999 Henry Spencer.  All rights reserved.
  6.  * 
  7.  * Development of this software was funded, in part, by Cray Research Inc.,
  8.  * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
  9.  * Corporation, none of whom are responsible for the results.  The author
  10.  * thanks all of them. 
  11.  * 
  12.  * Redistribution and use in source and binary forms -- with or without
  13.  * modification -- are permitted for any purpose, provided that
  14.  * redistributions in source form retain this entire copyright notice and
  15.  * indicate the origin and nature of any modifications.
  16.  * 
  17.  * I'd appreciate being given credit for this package in the documentation
  18.  * of software which uses it, but that is not a requirement.
  19.  * 
  20.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  21.  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  22.  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
  23.  * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  24.  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  25.  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  26.  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  27.  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  28.  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  29.  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30.  *
  31.  *
  32.  *
  33.  * One or two things that technically ought to be in here
  34.  * are actually in color.c, thanks to some incestuous relationships in
  35.  * the color chains.
  36.  */
  37. #define NISERR() VISERR(nfa->v)
  38. #define NERR(e) VERR(nfa->v, (e))
  39. /*
  40.  - newnfa - set up an NFA
  41.  ^ static struct nfa *newnfa(struct vars *, struct colormap *, struct nfa *);
  42.  */
  43. static struct nfa * /* the NFA, or NULL */
  44. newnfa(v, cm, parent)
  45. struct vars *v;
  46. struct colormap *cm;
  47. struct nfa *parent; /* NULL if primary NFA */
  48. {
  49. struct nfa *nfa;
  50. nfa = (struct nfa *)MALLOC(sizeof(struct nfa));
  51. if (nfa == NULL)
  52. return NULL;
  53. nfa->states = NULL;
  54. nfa->slast = NULL;
  55. nfa->free = NULL;
  56. nfa->nstates = 0;
  57. nfa->cm = cm;
  58. nfa->v = v;
  59. nfa->size = 0;
  60. nfa->bos[0] = nfa->bos[1] = COLORLESS;
  61. nfa->eos[0] = nfa->eos[1] = COLORLESS;
  62. nfa->parent = parent;
  63. nfa->post = newfstate(nfa, '@'); /* number 0 */
  64. nfa->pre = newfstate(nfa, '>'); /* number 1 */
  65. nfa->init = newstate(nfa); /* may become invalid later */
  66. nfa->final = newstate(nfa);
  67. if (ISERR()) {
  68. freenfa(nfa);
  69. return NULL;
  70. }
  71. rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->pre, nfa->init);
  72. newarc(nfa, '^', 1, nfa->pre, nfa->init);
  73. newarc(nfa, '^', 0, nfa->pre, nfa->init);
  74. rainbow(nfa, nfa->cm, PLAIN, COLORLESS, nfa->final, nfa->post);
  75. newarc(nfa, '$', 1, nfa->final, nfa->post);
  76. newarc(nfa, '$', 0, nfa->final, nfa->post);
  77. if (ISERR()) {
  78. freenfa(nfa);
  79. return NULL;
  80. }
  81. return nfa;
  82. }
  83. /*
  84.  - too_many_states - checks if the max states exceeds the compile-time value
  85.  ^ static int too_many_states(struct nfa *);
  86.  */
  87. static int
  88. too_many_states(nfa)
  89. struct nfa *nfa;
  90. {
  91. struct nfa *parent = nfa->parent;
  92. size_t sz = nfa->size;
  93. while (parent != NULL) {
  94. sz = parent->size;
  95. parent = parent->parent;
  96. }
  97. if (sz > REG_MAX_STATES)
  98. return 1;
  99. return 0;
  100. }
  101. /*
  102.  - increment_size - increases the tracked size of the NFA and its parents.
  103.  ^ static void increment_size(struct nfa *);
  104.  */
  105. static void
  106. increment_size(nfa)
  107. struct nfa *nfa;
  108. {
  109. struct nfa *parent = nfa->parent;
  110. nfa->size++;
  111. while (parent != NULL) {
  112. parent->size++;
  113. parent = parent->parent;
  114. }
  115. }
  116. /*
  117.  - decrement_size - increases the tracked size of the NFA and its parents.
  118.  ^ static void decrement_size(struct nfa *);
  119.  */
  120. static void
  121. decrement_size(nfa)
  122. struct nfa *nfa;
  123. {
  124. struct nfa *parent = nfa->parent;
  125. nfa->size--;
  126. while (parent != NULL) {
  127. parent->size--;
  128. parent = parent->parent;
  129. }
  130. }
  131. /*
  132.  - freenfa - free an entire NFA
  133.  ^ static VOID freenfa(struct nfa *);
  134.  */
  135. static VOID
  136. freenfa(nfa)
  137. struct nfa *nfa;
  138. {
  139. struct state *s;
  140. while ((s = nfa->states) != NULL) {
  141. s->nins = s->nouts = 0; /* don't worry about arcs */
  142. freestate(nfa, s);
  143. }
  144. while ((s = nfa->free) != NULL) {
  145. nfa->free = s->next;
  146. destroystate(nfa, s);
  147. }
  148. nfa->slast = NULL;
  149. nfa->nstates = -1;
  150. nfa->pre = NULL;
  151. nfa->post = NULL;
  152. FREE(nfa);
  153. }
  154. /*
  155.  - newstate - allocate an NFA state, with zero flag value
  156.  ^ static struct state *newstate(struct nfa *);
  157.  */
  158. static struct state * /* NULL on error */
  159. newstate(nfa)
  160. struct nfa *nfa;
  161. {
  162. struct state *s;
  163. if (too_many_states(nfa)) {
  164. /* XXX: add specific error for this */
  165. NERR(REG_ETOOBIG);
  166. return NULL;
  167. }
  168. if (nfa->free != NULL) {
  169. s = nfa->free;
  170. nfa->free = s->next;
  171. } else {
  172. s = (struct state *)MALLOC(sizeof(struct state));
  173. if (s == NULL) {
  174. NERR(REG_ESPACE);
  175. return NULL;
  176. }
  177. s->oas.next = NULL;
  178. s->free = NULL;
  179. s->noas = 0;
  180. }
  181. assert(nfa->nstates >= 0);
  182. s->no = nfa->nstates++;
  183. s->flag = 0;
  184. if (nfa->states == NULL)
  185. nfa->states = s;
  186. s->nins = 0;
  187. s->ins = NULL;
  188. s->nouts = 0;
  189. s->outs = NULL;
  190. s->tmp = NULL;
  191. s->next = NULL;
  192. if (nfa->slast != NULL) {
  193. assert(nfa->slast->next == NULL);
  194. nfa->slast->next = s;
  195. }
  196. s->prev = nfa->slast;
  197. nfa->slast = s;
  198. /* Track the current size and the parent size */
  199. increment_size(nfa);
  200. return s;
  201. }
  202. /*
  203.  - newfstate - allocate an NFA state with a specified flag value
  204.  ^ static struct state *newfstate(struct nfa *, int flag);
  205.  */
  206. static struct state * /* NULL on error */
  207. newfstate(nfa, flag)
  208. struct nfa *nfa;
  209. int flag;
  210. {
  211. struct state *s;
  212. s = newstate(nfa);
  213. if (s != NULL)
  214. s->flag = (char)flag;
  215. return s;
  216. }
  217. /*
  218.  - dropstate - delete a state's inarcs and outarcs and free it
  219.  ^ static VOID dropstate(struct nfa *, struct state *);
  220.  */
  221. static VOID
  222. dropstate(nfa, s)
  223. struct nfa *nfa;
  224. struct state *s;
  225. {
  226. struct arc *a;
  227. while ((a = s->ins) != NULL)
  228. freearc(nfa, a);
  229. while ((a = s->outs) != NULL)
  230. freearc(nfa, a);
  231. freestate(nfa, s);
  232. }
  233. /*
  234.  - freestate - free a state, which has no in-arcs or out-arcs
  235.  ^ static VOID freestate(struct nfa *, struct state *);
  236.  */
  237. static VOID
  238. freestate(nfa, s)
  239. struct nfa *nfa;
  240. struct state *s;
  241. {
  242. assert(s != NULL);
  243. assert(s->nins == 0 && s->nouts == 0);
  244. s->no = FREESTATE;
  245. s->flag = 0;
  246. if (s->next != NULL)
  247. s->next->prev = s->prev;
  248. else {
  249. assert(s == nfa->slast);
  250. nfa->slast = s->prev;
  251. }
  252. if (s->prev != NULL)
  253. s->prev->next = s->next;
  254. else {
  255. assert(s == nfa->states);
  256. nfa->states = s->next;
  257. }
  258. s->prev = NULL;
  259. s->next = nfa->free; /* don't delete it, put it on the free list */
  260. nfa->free = s;
  261. decrement_size(nfa);
  262. }
  263. /*
  264.  - destroystate - really get rid of an already-freed state
  265.  ^ static VOID destroystate(struct nfa *, struct state *);
  266.  */
  267. static VOID
  268. destroystate(nfa, s)
  269. struct nfa *nfa;
  270. struct state *s;
  271. {
  272. struct arcbatch *ab;
  273. struct arcbatch *abnext;
  274. assert(s->no == FREESTATE);
  275. for (ab = s->oas.next; ab != NULL; ab = abnext) {
  276. abnext = ab->next;
  277. FREE(ab);
  278. }
  279. s->ins = NULL;
  280. s->outs = NULL;
  281. s->next = NULL;
  282. FREE(s);
  283. }
  284. /*
  285.  - newarc - set up a new arc within an NFA
  286.  ^ static VOID newarc(struct nfa *, int, pcolor, struct state *, 
  287.  ^ struct state *);
  288.  */
  289. static VOID
  290. newarc(nfa, t, co, from, to)
  291. struct nfa *nfa;
  292. int t;
  293. pcolor co;
  294. struct state *from;
  295. struct state *to;
  296. {
  297. struct arc *a;
  298. assert(from != NULL && to != NULL);
  299. /* check for duplicates */
  300. for (a = from->outs; a != NULL; a = a->outchain)
  301. if (a->to == to && a->co == co && a->type == t)
  302. return;
  303. a = allocarc(nfa, from);
  304. if (NISERR())
  305. return;
  306. assert(a != NULL);
  307. a->type = t;
  308. a->co = (color)co;
  309. a->to = to;
  310. a->from = from;
  311. /*
  312.  * Put the new arc on the beginning, not the end, of the chains.
  313.  * Not only is this easier, it has the very useful side effect that 
  314.  * deleting the most-recently-added arc is the cheapest case rather
  315.  * than the most expensive one.
  316.  */
  317. a->inchain = to->ins;
  318. to->ins = a;
  319. a->outchain = from->outs;
  320. from->outs = a;
  321. from->nouts++;
  322. to->nins++;
  323. if (COLORED(a) && nfa->parent == NULL)
  324. colorchain(nfa->cm, a);
  325. return;
  326. }
  327. /*
  328.  - allocarc - allocate a new out-arc within a state
  329.  ^ static struct arc *allocarc(struct nfa *, struct state *);
  330.  */
  331. static struct arc * /* NULL for failure */
  332. allocarc(nfa, s)
  333. struct nfa *nfa;
  334. struct state *s;
  335. {
  336. struct arc *a;
  337. struct arcbatch *new;
  338. int i;
  339. /* shortcut */
  340. if (s->free == NULL && s->noas < ABSIZE) {
  341. a = &s->oas.a[s->noas];
  342. s->noas++;
  343. return a;
  344. }
  345. /* if none at hand, get more */
  346. if (s->free == NULL) {
  347. new = (struct arcbatch *)MALLOC(sizeof(struct arcbatch));
  348. if (new == NULL) {
  349. NERR(REG_ESPACE);
  350. return NULL;
  351. }
  352. new->next = s->oas.next;
  353. s->oas.next = new;
  354. for (i = 0; i < ABSIZE; i++) {
  355. new->a[i].type = 0;
  356. new->a[i].freechain = &new->a[i+1];
  357. }
  358. new->a[ABSIZE-1].freechain = NULL;
  359. s->free = &new->a[0];
  360. }
  361. assert(s->free != NULL);
  362. a = s->free;
  363. s->free = a->freechain;
  364. return a;
  365. }
  366. /*
  367.  - freearc - free an arc
  368.  ^ static VOID freearc(struct nfa *, struct arc *);
  369.  */
  370. static VOID
  371. freearc(nfa, victim)
  372. struct nfa *nfa;
  373. struct arc *victim;
  374. {
  375. struct state *from = victim->from;
  376. struct state *to = victim->to;
  377. struct arc *a;
  378. assert(victim->type != 0);
  379. /* take it off color chain if necessary */
  380. if (COLORED(victim) && nfa->parent == NULL)
  381. uncolorchain(nfa->cm, victim);
  382. /* take it off source's out-chain */
  383. assert(from != NULL);
  384. assert(from->outs != NULL);
  385. a = from->outs;
  386. if (a == victim) /* simple case:  first in chain */
  387. from->outs = victim->outchain;
  388. else {
  389. for (; a != NULL && a->outchain != victim; a = a->outchain)
  390. continue;
  391. assert(a != NULL);
  392. a->outchain = victim->outchain;
  393. }
  394. from->nouts--;
  395. /* take it off target's in-chain */
  396. assert(to != NULL);
  397. assert(to->ins != NULL);
  398. a = to->ins;
  399. if (a == victim) /* simple case:  first in chain */
  400. to->ins = victim->inchain;
  401. else {
  402. for (; a != NULL && a->inchain != victim; a = a->inchain)
  403. continue;
  404. assert(a != NULL);
  405. a->inchain = victim->inchain;
  406. }
  407. to->nins--;
  408. /* clean up and place on free list */
  409. victim->type = 0;
  410. victim->from = NULL; /* precautions... */
  411. victim->to = NULL;
  412. victim->inchain = NULL;
  413. victim->outchain = NULL;
  414. victim->freechain = from->free;
  415. from->free = victim;
  416. }
  417. /*
  418.  - findarc - find arc, if any, from given source with given type and color
  419.  * If there is more than one such arc, the result is random.
  420.  ^ static struct arc *findarc(struct state *, int, pcolor);
  421.  */
  422. static struct arc *
  423. findarc(s, type, co)
  424. struct state *s;
  425. int type;
  426. pcolor co;
  427. {
  428. struct arc *a;
  429. for (a = s->outs; a != NULL; a = a->outchain)
  430. if (a->type == type && a->co == co)
  431. return a;
  432. return NULL;
  433. }
  434. /*
  435.  - cparc - allocate a new arc within an NFA, copying details from old one
  436.  ^ static VOID cparc(struct nfa *, struct arc *, struct state *, 
  437.  ^  struct state *);
  438.  */
  439. static VOID
  440. cparc(nfa, oa, from, to)
  441. struct nfa *nfa;
  442. struct arc *oa;
  443. struct state *from;
  444. struct state *to;
  445. {
  446. newarc(nfa, oa->type, oa->co, from, to);
  447. }
  448. /*
  449.  - moveins - move all in arcs of a state to another state
  450.  * You might think this could be done better by just updating the
  451.  * existing arcs, and you would be right if it weren't for the desire
  452.  * for duplicate suppression, which makes it easier to just make new
  453.  * ones to exploit the suppression built into newarc.
  454.  ^ static VOID moveins(struct nfa *, struct state *, struct state *);
  455.  */
  456. static VOID
  457. moveins(nfa, old, new)
  458. struct nfa *nfa;
  459. struct state *old;
  460. struct state *new;
  461. {
  462. struct arc *a;
  463. assert(old != new);
  464. while ((a = old->ins) != NULL) {
  465. cparc(nfa, a, a->from, new);
  466. freearc(nfa, a);
  467. }
  468. assert(old->nins == 0);
  469. assert(old->ins == NULL);
  470. }
  471. /*
  472.  - copyins - copy all in arcs of a state to another state
  473.  ^ static VOID copyins(struct nfa *, struct state *, struct state *);
  474.  */
  475. static VOID
  476. copyins(nfa, old, new)
  477. struct nfa *nfa;
  478. struct state *old;
  479. struct state *new;
  480. {
  481. struct arc *a;
  482. assert(old != new);
  483. for (a = old->ins; a != NULL; a = a->inchain)
  484. cparc(nfa, a, a->from, new);
  485. }
  486. /*
  487.  - moveouts - move all out arcs of a state to another state
  488.  ^ static VOID moveouts(struct nfa *, struct state *, struct state *);
  489.  */
  490. static VOID
  491. moveouts(nfa, old, new)
  492. struct nfa *nfa;
  493. struct state *old;
  494. struct state *new;
  495. {
  496. struct arc *a;
  497. assert(old != new);
  498. while ((a = old->outs) != NULL) {
  499. cparc(nfa, a, new, a->to);
  500. freearc(nfa, a);
  501. }
  502. }
  503. /*
  504.  - copyouts - copy all out arcs of a state to another state
  505.  ^ static VOID copyouts(struct nfa *, struct state *, struct state *);
  506.  */
  507. static VOID
  508. copyouts(nfa, old, new)
  509. struct nfa *nfa;
  510. struct state *old;
  511. struct state *new;
  512. {
  513. struct arc *a;
  514. assert(old != new);
  515. for (a = old->outs; a != NULL; a = a->outchain)
  516. cparc(nfa, a, new, a->to);
  517. }
  518. /*
  519.  - cloneouts - copy out arcs of a state to another state pair, modifying type
  520.  ^ static VOID cloneouts(struct nfa *, struct state *, struct state *,
  521.  ^  struct state *, int);
  522.  */
  523. static VOID
  524. cloneouts(nfa, old, from, to, type)
  525. struct nfa *nfa;
  526. struct state *old;
  527. struct state *from;
  528. struct state *to;
  529. int type;
  530. {
  531. struct arc *a;
  532. assert(old != from);
  533. for (a = old->outs; a != NULL; a = a->outchain)
  534. newarc(nfa, type, a->co, from, to);
  535. }
  536. /*
  537.  - delsub - delete a sub-NFA, updating subre pointers if necessary
  538.  * This uses a recursive traversal of the sub-NFA, marking already-seen
  539.  * states using their tmp pointer.
  540.  ^ static VOID delsub(struct nfa *, struct state *, struct state *);
  541.  */
  542. static VOID
  543. delsub(nfa, lp, rp)
  544. struct nfa *nfa;
  545. struct state *lp; /* the sub-NFA goes from here... */
  546. struct state *rp; /* ...to here, *not* inclusive */
  547. {
  548. assert(lp != rp);
  549. rp->tmp = rp; /* mark end */
  550. deltraverse(nfa, lp, lp);
  551. assert(lp->nouts == 0 && rp->nins == 0); /* did the job */
  552. assert(lp->no != FREESTATE && rp->no != FREESTATE); /* no more */
  553. rp->tmp = NULL; /* unmark end */
  554. lp->tmp = NULL; /* and begin, marked by deltraverse */
  555. }
  556. /*
  557.  - deltraverse - the recursive heart of delsub
  558.  * This routine's basic job is to destroy all out-arcs of the state.
  559.  ^ static VOID deltraverse(struct nfa *, struct state *, struct state *);
  560.  */
  561. static VOID
  562. deltraverse(nfa, leftend, s)
  563. struct nfa *nfa;
  564. struct state *leftend;
  565. struct state *s;
  566. {
  567. struct arc *a;
  568. struct state *to;
  569. if (s->nouts == 0)
  570. return; /* nothing to do */
  571. if (s->tmp != NULL)
  572. return; /* already in progress */
  573. s->tmp = s; /* mark as in progress */
  574. while ((a = s->outs) != NULL) {
  575. to = a->to;
  576. deltraverse(nfa, leftend, to);
  577. assert(to->nouts == 0 || to->tmp != NULL);
  578. freearc(nfa, a);
  579. if (to->nins == 0 && to->tmp == NULL) {
  580. assert(to->nouts == 0);
  581. freestate(nfa, to);
  582. }
  583. }
  584. assert(s->no != FREESTATE); /* we're still here */
  585. assert(s == leftend || s->nins != 0); /* and still reachable */
  586. assert(s->nouts == 0); /* but have no outarcs */
  587. s->tmp = NULL; /* we're done here */
  588. }
  589. /*
  590.  - dupnfa - duplicate sub-NFA
  591.  * Another recursive traversal, this time using tmp to point to duplicates
  592.  * as well as mark already-seen states.  (You knew there was a reason why
  593.  * it's a state pointer, didn't you? :-))
  594.  ^ static VOID dupnfa(struct nfa *, struct state *, struct state *, 
  595.  ^  struct state *, struct state *);
  596.  */
  597. static VOID
  598. dupnfa(nfa, start, stop, from, to)
  599. struct nfa *nfa;
  600. struct state *start; /* duplicate of subNFA starting here */
  601. struct state *stop; /* and stopping here */
  602. struct state *from; /* stringing duplicate from here */
  603. struct state *to; /* to here */
  604. {
  605. if (start == stop) {
  606. newarc(nfa, EMPTY, 0, from, to);
  607. return;
  608. }
  609. stop->tmp = to;
  610. duptraverse(nfa, start, from);
  611. /* done, except for clearing out the tmp pointers */
  612. stop->tmp = NULL;
  613. cleartraverse(nfa, start);
  614. }
  615. /*
  616.  - duptraverse - recursive heart of dupnfa
  617.  ^ static VOID duptraverse(struct nfa *, struct state *, struct state *);
  618.  */
  619. static VOID
  620. duptraverse(nfa, s, stmp)
  621. struct nfa *nfa;
  622. struct state *s;
  623. struct state *stmp; /* s's duplicate, or NULL */
  624. {
  625. struct arc *a;
  626. if (s->tmp != NULL)
  627. return; /* already done */
  628. s->tmp = (stmp == NULL) ? newstate(nfa) : stmp;
  629. if (s->tmp == NULL) {
  630. assert(NISERR());
  631. return;
  632. }
  633. for (a = s->outs; a != NULL && !NISERR(); a = a->outchain) {
  634. duptraverse(nfa, a->to, (struct state *)NULL);
  635. if (NISERR())
  636. break;
  637. assert(a->to->tmp != NULL);
  638. cparc(nfa, a, s->tmp, a->to->tmp);
  639. }
  640. }
  641. /*
  642.  - cleartraverse - recursive cleanup for algorithms that leave tmp ptrs set
  643.  ^ static VOID cleartraverse(struct nfa *, struct state *);
  644.  */
  645. static VOID
  646. cleartraverse(nfa, s)
  647. struct nfa *nfa;
  648. struct state *s;
  649. {
  650. struct arc *a;
  651. if (s->tmp == NULL)
  652. return;
  653. s->tmp = NULL;
  654. for (a = s->outs; a != NULL; a = a->outchain)
  655. cleartraverse(nfa, a->to);
  656. }
  657. /*
  658.  - specialcolors - fill in special colors for an NFA
  659.  ^ static VOID specialcolors(struct nfa *);
  660.  */
  661. static VOID
  662. specialcolors(nfa)
  663. struct nfa *nfa;
  664. {
  665. /* false colors for BOS, BOL, EOS, EOL */
  666. if (nfa->parent == NULL) {
  667. nfa->bos[0] = pseudocolor(nfa->cm);
  668. nfa->bos[1] = pseudocolor(nfa->cm);
  669. nfa->eos[0] = pseudocolor(nfa->cm);
  670. nfa->eos[1] = pseudocolor(nfa->cm);
  671. } else {
  672. assert(nfa->parent->bos[0] != COLORLESS);
  673. nfa->bos[0] = nfa->parent->bos[0];
  674. assert(nfa->parent->bos[1] != COLORLESS);
  675. nfa->bos[1] = nfa->parent->bos[1];
  676. assert(nfa->parent->eos[0] != COLORLESS);
  677. nfa->eos[0] = nfa->parent->eos[0];
  678. assert(nfa->parent->eos[1] != COLORLESS);
  679. nfa->eos[1] = nfa->parent->eos[1];
  680. }
  681. }
  682. /*
  683.  - optimize - optimize an NFA
  684.  ^ static long optimize(struct nfa *, FILE *);
  685.  */
  686. static long /* re_info bits */
  687. optimize(nfa, f)
  688. struct nfa *nfa;
  689. FILE *f; /* for debug output; NULL none */
  690. {
  691. int verbose = (f != NULL) ? 1 : 0;
  692. if (verbose)
  693. fprintf(f, "ninitial cleanup:n");
  694. cleanup(nfa); /* may simplify situation */
  695. if (verbose)
  696. dumpnfa(nfa, f);
  697. if (verbose)
  698. fprintf(f, "nempties:n");
  699. fixempties(nfa, f); /* get rid of EMPTY arcs */
  700. if (verbose)
  701. fprintf(f, "nconstraints:n");
  702. pullback(nfa, f); /* pull back constraints backward */
  703. pushfwd(nfa, f); /* push fwd constraints forward */
  704. if (verbose)
  705. fprintf(f, "nfinal cleanup:n");
  706. cleanup(nfa); /* final tidying */
  707. return analyze(nfa); /* and analysis */
  708. }
  709. /*
  710.  - pullback - pull back constraints backward to (with luck) eliminate them
  711.  ^ static VOID pullback(struct nfa *, FILE *);
  712.  */
  713. static VOID
  714. pullback(nfa, f)
  715. struct nfa *nfa;
  716. FILE *f; /* for debug output; NULL none */
  717. {
  718. struct state *s;
  719. struct state *nexts;
  720. struct arc *a;
  721. struct arc *nexta;
  722. int progress;
  723. /* find and pull until there are no more */
  724. do {
  725. progress = 0;
  726. for (s = nfa->states; s != NULL && !NISERR(); s = nexts) {
  727. nexts = s->next;
  728. for (a = s->outs; a != NULL && !NISERR(); a = nexta) {
  729. nexta = a->outchain;
  730. if (a->type == '^' || a->type == BEHIND)
  731. if (pull(nfa, a))
  732. progress = 1;
  733. assert(nexta == NULL || s->no != FREESTATE);
  734. }
  735. }
  736. if (progress && f != NULL)
  737. dumpnfa(nfa, f);
  738. } while (progress && !NISERR());
  739. if (NISERR())
  740. return;
  741. for (a = nfa->pre->outs; a != NULL; a = nexta) {
  742. nexta = a->outchain;
  743. if (a->type == '^') {
  744. assert(a->co == 0 || a->co == 1);
  745. newarc(nfa, PLAIN, nfa->bos[a->co], a->from, a->to);
  746. freearc(nfa, a);
  747. }
  748. }
  749. }
  750. /*
  751.  - pull - pull a back constraint backward past its source state
  752.  * A significant property of this function is that it deletes at most
  753.  * one state -- the constraint's from state -- and only if the constraint
  754.  * was that state's last outarc.
  755.  ^ static int pull(struct nfa *, struct arc *);
  756.  */
  757. static int /* 0 couldn't, 1 could */
  758. pull(nfa, con)
  759. struct nfa *nfa;
  760. struct arc *con;
  761. {
  762. struct state *from = con->from;
  763. struct state *to = con->to;
  764. struct arc *a;
  765. struct arc *nexta;
  766. struct state *s;
  767. if (from == to) { /* circular constraint is pointless */
  768. freearc(nfa, con);
  769. return 1;
  770. }
  771. if (from->flag) /* can't pull back beyond start */
  772. return 0;
  773. if (from->nins == 0) { /* unreachable */
  774. freearc(nfa, con);
  775. return 1;
  776. }
  777. /*
  778.  * DGP 2007-11-15: Cloning a state with a circular constraint on its
  779.  * list of outs can lead to trouble [Bug 1810038], so get rid of them
  780.  * first.
  781.  */
  782. for (a = from->outs; a != NULL; a = nexta) {
  783. nexta = a->outchain;
  784. switch (a->type) {
  785. case '^':
  786. case '$':
  787. case BEHIND:
  788. case AHEAD:
  789. if (from == a->to) {
  790. freearc(nfa, a);
  791. }
  792. break;
  793. }
  794. }
  795. /* first, clone from state if necessary to avoid other outarcs */
  796. if (from->nouts > 1) {
  797. s = newstate(nfa);
  798. if (NISERR())
  799. return 0;
  800. assert(to != from); /* con is not an inarc */
  801. copyins(nfa, from, s); /* duplicate inarcs */
  802. cparc(nfa, con, s, to); /* move constraint arc */
  803. freearc(nfa, con);
  804. from = s;
  805. con = from->outs;
  806. }
  807. assert(from->nouts == 1);
  808. /* propagate the constraint into the from state's inarcs */
  809. for (a = from->ins; a != NULL; a = nexta) {
  810. nexta = a->inchain;
  811. switch (combine(con, a)) {
  812. case INCOMPATIBLE: /* destroy the arc */
  813. freearc(nfa, a);
  814. break;
  815. case SATISFIED: /* no action needed */
  816. break;
  817. case COMPATIBLE: /* swap the two arcs, more or less */
  818. s = newstate(nfa);
  819. if (NISERR())
  820. return 0;
  821. cparc(nfa, a, s, to); /* anticipate move */
  822. cparc(nfa, con, a->from, s);
  823. if (NISERR())
  824. return 0;
  825. freearc(nfa, a);
  826. break;
  827. default:
  828. assert(NOTREACHED);
  829. break;
  830. }
  831. }
  832. /* remaining inarcs, if any, incorporate the constraint */
  833. moveins(nfa, from, to);
  834. dropstate(nfa, from); /* will free the constraint */
  835. return 1;
  836. }
  837. /*
  838.  - pushfwd - push forward constraints forward to (with luck) eliminate them
  839.  ^ static VOID pushfwd(struct nfa *, FILE *);
  840.  */
  841. static VOID
  842. pushfwd(nfa, f)
  843. struct nfa *nfa;
  844. FILE *f; /* for debug output; NULL none */
  845. {
  846. struct state *s;
  847. struct state *nexts;
  848. struct arc *a;
  849. struct arc *nexta;
  850. int progress;
  851. /* find and push until there are no more */
  852. do {
  853. progress = 0;
  854. for (s = nfa->states; s != NULL && !NISERR(); s = nexts) {
  855. nexts = s->next;
  856. for (a = s->ins; a != NULL && !NISERR(); a = nexta) {
  857. nexta = a->inchain;
  858. if (a->type == '$' || a->type == AHEAD)
  859. if (push(nfa, a))
  860. progress = 1;
  861. assert(nexta == NULL || s->no != FREESTATE);
  862. }
  863. }
  864. if (progress && f != NULL)
  865. dumpnfa(nfa, f);
  866. } while (progress && !NISERR());
  867. if (NISERR())
  868. return;
  869. for (a = nfa->post->ins; a != NULL; a = nexta) {
  870. nexta = a->inchain;
  871. if (a->type == '$') {
  872. assert(a->co == 0 || a->co == 1);
  873. newarc(nfa, PLAIN, nfa->eos[a->co], a->from, a->to);
  874. freearc(nfa, a);
  875. }
  876. }
  877. }
  878. /*
  879.  - push - push a forward constraint forward past its destination state
  880.  * A significant property of this function is that it deletes at most
  881.  * one state -- the constraint's to state -- and only if the constraint
  882.  * was that state's last inarc.
  883.  ^ static int push(struct nfa *, struct arc *);
  884.  */
  885. static int /* 0 couldn't, 1 could */
  886. push(nfa, con)
  887. struct nfa *nfa;
  888. struct arc *con;
  889. {
  890. struct state *from = con->from;
  891. struct state *to = con->to;
  892. struct arc *a;
  893. struct arc *nexta;
  894. struct state *s;
  895. if (to == from) { /* circular constraint is pointless */
  896. freearc(nfa, con);
  897. return 1;
  898. }
  899. if (to->flag) /* can't push forward beyond end */
  900. return 0;
  901. if (to->nouts == 0) { /* dead end */
  902. freearc(nfa, con);
  903. return 1;
  904. }
  905. /*
  906.  * DGP 2007-11-15: Here we duplicate the same protections as appear
  907.  * in pull() above to avoid troubles with cloning a state with a
  908.  * circular constraint on its list of ins.  It is not clear whether
  909.  * this is necessary, or is protecting against a "can't happen".
  910.  * Any test case that actually leads to a freearc() call here would
  911.  * be a welcome addition to the test suite.
  912.  */
  913. for (a = to->ins; a != NULL; a = nexta) {
  914. nexta = a->inchain;
  915. switch (a->type) {
  916. case '^':
  917. case '$':
  918. case BEHIND:
  919. case AHEAD:
  920. if (a->from == to) {
  921. freearc(nfa, a);
  922. }
  923. break;
  924. }
  925. }
  926. /* first, clone to state if necessary to avoid other inarcs */
  927. if (to->nins > 1) {
  928. s = newstate(nfa);
  929. if (NISERR())
  930. return 0;
  931. copyouts(nfa, to, s); /* duplicate outarcs */
  932. cparc(nfa, con, from, s); /* move constraint */
  933. freearc(nfa, con);
  934. to = s;
  935. con = to->ins;
  936. }
  937. assert(to->nins == 1);
  938. /* propagate the constraint into the to state's outarcs */
  939. for (a = to->outs; a != NULL; a = nexta) {
  940. nexta = a->outchain;
  941. switch (combine(con, a)) {
  942. case INCOMPATIBLE: /* destroy the arc */
  943. freearc(nfa, a);
  944. break;
  945. case SATISFIED: /* no action needed */
  946. break;
  947. case COMPATIBLE: /* swap the two arcs, more or less */
  948. s = newstate(nfa);
  949. if (NISERR())
  950. return 0;
  951. cparc(nfa, con, s, a->to); /* anticipate move */
  952. cparc(nfa, a, from, s);
  953. if (NISERR())
  954. return 0;
  955. freearc(nfa, a);
  956. break;
  957. default:
  958. assert(NOTREACHED);
  959. break;
  960. }
  961. }
  962. /* remaining outarcs, if any, incorporate the constraint */
  963. moveouts(nfa, to, from);
  964. dropstate(nfa, to); /* will free the constraint */
  965. return 1;
  966. }
  967. /*
  968.  - combine - constraint lands on an arc, what happens?
  969.  ^ #def INCOMPATIBLE 1 // destroys arc
  970.  ^ #def SATISFIED 2 // constraint satisfied
  971.  ^ #def COMPATIBLE 3 // compatible but not satisfied yet
  972.  ^ static int combine(struct arc *, struct arc *);
  973.  */
  974. static int
  975. combine(con, a)
  976. struct arc *con;
  977. struct arc *a;
  978. {
  979. # define CA(ct,at) (((ct)<<CHAR_BIT) | (at))
  980. switch (CA(con->type, a->type)) {
  981. case CA('^', PLAIN): /* newlines are handled separately */
  982. case CA('$', PLAIN):
  983. return INCOMPATIBLE;
  984. break;
  985. case CA(AHEAD, PLAIN): /* color constraints meet colors */
  986. case CA(BEHIND, PLAIN):
  987. if (con->co == a->co)
  988. return SATISFIED;
  989. return INCOMPATIBLE;
  990. break;
  991. case CA('^', '^'): /* collision, similar constraints */
  992. case CA('$', '$'):
  993. case CA(AHEAD, AHEAD):
  994. case CA(BEHIND, BEHIND):
  995. if (con->co == a->co) /* true duplication */
  996. return SATISFIED;
  997. return INCOMPATIBLE;
  998. break;
  999. case CA('^', BEHIND): /* collision, dissimilar constraints */
  1000. case CA(BEHIND, '^'):
  1001. case CA('$', AHEAD):
  1002. case CA(AHEAD, '$'):
  1003. return INCOMPATIBLE;
  1004. break;
  1005. case CA('^', '$'): /* constraints passing each other */
  1006. case CA('^', AHEAD):
  1007. case CA(BEHIND, '$'):
  1008. case CA(BEHIND, AHEAD):
  1009. case CA('$', '^'):
  1010. case CA('$', BEHIND):
  1011. case CA(AHEAD, '^'):
  1012. case CA(AHEAD, BEHIND):
  1013. case CA('^', LACON):
  1014. case CA(BEHIND, LACON):
  1015. case CA('$', LACON):
  1016. case CA(AHEAD, LACON):
  1017. return COMPATIBLE;
  1018. break;
  1019. }
  1020. assert(NOTREACHED);
  1021. return INCOMPATIBLE; /* for benefit of blind compilers */
  1022. }
  1023. /*
  1024.  - fixempties - get rid of EMPTY arcs
  1025.  ^ static VOID fixempties(struct nfa *, FILE *);
  1026.  */
  1027. static VOID
  1028. fixempties(nfa, f)
  1029. struct nfa *nfa;
  1030. FILE *f; /* for debug output; NULL none */
  1031. {
  1032. struct state *s;
  1033. struct state *nexts;
  1034. struct arc *a;
  1035. struct arc *nexta;
  1036. int progress;
  1037. /* find and eliminate empties until there are no more */
  1038. do {
  1039. progress = 0;
  1040. for (s = nfa->states; s != NULL && !NISERR()
  1041. && s->no != FREESTATE; s = nexts) {
  1042. nexts = s->next;
  1043. for (a = s->outs; a != NULL && !NISERR(); a = nexta) {
  1044. nexta = a->outchain;
  1045. if (a->type == EMPTY && unempty(nfa, a))
  1046. progress = 1;
  1047. assert(nexta == NULL || s->no != FREESTATE);
  1048. }
  1049. }
  1050. if (progress && f != NULL)
  1051. dumpnfa(nfa, f);
  1052. } while (progress && !NISERR());
  1053. }
  1054. /*
  1055.  - unempty - optimize out an EMPTY arc, if possible
  1056.  * Actually, as it stands this function always succeeds, but the return
  1057.  * value is kept with an eye on possible future changes.
  1058.  ^ static int unempty(struct nfa *, struct arc *);
  1059.  */
  1060. static int /* 0 couldn't, 1 could */
  1061. unempty(nfa, a)
  1062. struct nfa *nfa;
  1063. struct arc *a;
  1064. {
  1065. struct state *from = a->from;
  1066. struct state *to = a->to;
  1067. int usefrom; /* work on from, as opposed to to? */
  1068. assert(a->type == EMPTY);
  1069. assert(from != nfa->pre && to != nfa->post);
  1070. if (from == to) { /* vacuous loop */
  1071. freearc(nfa, a);
  1072. return 1;
  1073. }
  1074. /* decide which end to work on */
  1075. usefrom = 1; /* default:  attack from */
  1076. if (from->nouts > to->nins)
  1077. usefrom = 0;
  1078. else if (from->nouts == to->nins) {
  1079. /* decide on secondary issue:  move/copy fewest arcs */
  1080. if (from->nins > to->nouts)
  1081. usefrom = 0;
  1082. }
  1083. freearc(nfa, a);
  1084. if (usefrom) {
  1085. if (from->nouts == 0) {
  1086. /* was the state's only outarc */
  1087. moveins(nfa, from, to);
  1088. freestate(nfa, from);
  1089. } else
  1090. copyins(nfa, from, to);
  1091. } else {
  1092. if (to->nins == 0) {
  1093. /* was the state's only inarc */
  1094. moveouts(nfa, to, from);
  1095. freestate(nfa, to);
  1096. } else
  1097. copyouts(nfa, to, from);
  1098. }
  1099. return 1;
  1100. }
  1101. /*
  1102.  - cleanup - clean up NFA after optimizations
  1103.  ^ static VOID cleanup(struct nfa *);
  1104.  */
  1105. static VOID
  1106. cleanup(nfa)
  1107. struct nfa *nfa;
  1108. {
  1109. struct state *s;
  1110. struct state *nexts;
  1111. int n;
  1112. /* clear out unreachable or dead-end states */
  1113. /* use pre to mark reachable, then post to mark can-reach-post */
  1114. markreachable(nfa, nfa->pre, (struct state *)NULL, nfa->pre);
  1115. markcanreach(nfa, nfa->post, nfa->pre, nfa->post);
  1116. for (s = nfa->states; s != NULL; s = nexts) {
  1117. nexts = s->next;
  1118. if (s->tmp != nfa->post && !s->flag)
  1119. dropstate(nfa, s);
  1120. }
  1121. assert(nfa->post->nins == 0 || nfa->post->tmp == nfa->post);
  1122. cleartraverse(nfa, nfa->pre);
  1123. assert(nfa->post->nins == 0 || nfa->post->tmp == NULL);
  1124. /* the nins==0 (final unreachable) case will be caught later */
  1125. /* renumber surviving states */
  1126. n = 0;
  1127. for (s = nfa->states; s != NULL; s = s->next)
  1128. s->no = n++;
  1129. nfa->nstates = n;
  1130. }
  1131. /*
  1132.  - markreachable - recursive marking of reachable states
  1133.  ^ static VOID markreachable(struct nfa *, struct state *, struct state *,
  1134.  ^  struct state *);
  1135.  */
  1136. static VOID
  1137. markreachable(nfa, s, okay, mark)
  1138. struct nfa *nfa;
  1139. struct state *s;
  1140. struct state *okay; /* consider only states with this mark */
  1141. struct state *mark; /* the value to mark with */
  1142. {
  1143. struct arc *a;
  1144. if (s->tmp != okay)
  1145. return;
  1146. s->tmp = mark;
  1147. for (a = s->outs; a != NULL; a = a->outchain)
  1148. markreachable(nfa, a->to, okay, mark);
  1149. }
  1150. /*
  1151.  - markcanreach - recursive marking of states which can reach here
  1152.  ^ static VOID markcanreach(struct nfa *, struct state *, struct state *,
  1153.  ^  struct state *);
  1154.  */
  1155. static VOID
  1156. markcanreach(nfa, s, okay, mark)
  1157. struct nfa *nfa;
  1158. struct state *s;
  1159. struct state *okay; /* consider only states with this mark */
  1160. struct state *mark; /* the value to mark with */
  1161. {
  1162. struct arc *a;
  1163. if (s->tmp != okay)
  1164. return;
  1165. s->tmp = mark;
  1166. for (a = s->ins; a != NULL; a = a->inchain)
  1167. markcanreach(nfa, a->from, okay, mark);
  1168. }
  1169. /*
  1170.  - analyze - ascertain potentially-useful facts about an optimized NFA
  1171.  ^ static long analyze(struct nfa *);
  1172.  */
  1173. static long /* re_info bits to be ORed in */
  1174. analyze(nfa)
  1175. struct nfa *nfa;
  1176. {
  1177. struct arc *a;
  1178. struct arc *aa;
  1179. if (nfa->pre->outs == NULL)
  1180. return REG_UIMPOSSIBLE;
  1181. for (a = nfa->pre->outs; a != NULL; a = a->outchain)
  1182. for (aa = a->to->outs; aa != NULL; aa = aa->outchain)
  1183. if (aa->to == nfa->post)
  1184. return REG_UEMPTYMATCH;
  1185. return 0;
  1186. }
  1187. /*
  1188.  - compact - compact an NFA
  1189.  ^ static VOID compact(struct nfa *, struct cnfa *);
  1190.  */
  1191. static VOID
  1192. compact(nfa, cnfa)
  1193. struct nfa *nfa;
  1194. struct cnfa *cnfa;
  1195. {
  1196. struct state *s;
  1197. struct arc *a;
  1198. size_t nstates;
  1199. size_t narcs;
  1200. struct carc *ca;
  1201. struct carc *first;
  1202. assert (!NISERR());
  1203. nstates = 0;
  1204. narcs = 0;
  1205. for (s = nfa->states; s != NULL; s = s->next) {
  1206. nstates++;
  1207. narcs += 1 + s->nouts + 1;
  1208. /* 1 as a fake for flags, nouts for arcs, 1 as endmarker */
  1209. }
  1210. cnfa->states = (struct carc **)MALLOC(nstates * sizeof(struct carc *));
  1211. cnfa->arcs = (struct carc *)MALLOC(narcs * sizeof(struct carc));
  1212. if (cnfa->states == NULL || cnfa->arcs == NULL) {
  1213. if (cnfa->states != NULL)
  1214. FREE(cnfa->states);
  1215. if (cnfa->arcs != NULL)
  1216. FREE(cnfa->arcs);
  1217. NERR(REG_ESPACE);
  1218. return;
  1219. }
  1220. cnfa->nstates = nstates;
  1221. cnfa->pre = nfa->pre->no;
  1222. cnfa->post = nfa->post->no;
  1223. cnfa->bos[0] = nfa->bos[0];
  1224. cnfa->bos[1] = nfa->bos[1];
  1225. cnfa->eos[0] = nfa->eos[0];
  1226. cnfa->eos[1] = nfa->eos[1];
  1227. cnfa->ncolors = maxcolor(nfa->cm) + 1;
  1228. cnfa->flags = 0;
  1229. ca = cnfa->arcs;
  1230. for (s = nfa->states; s != NULL; s = s->next) {
  1231. assert((size_t)s->no < nstates);
  1232. cnfa->states[s->no] = ca;
  1233. ca->co = 0; /* clear and skip flags "arc" */
  1234. ca++;
  1235. first = ca;
  1236. for (a = s->outs; a != NULL; a = a->outchain)
  1237. switch (a->type) {
  1238. case PLAIN:
  1239. ca->co = a->co;
  1240. ca->to = a->to->no;
  1241. ca++;
  1242. break;
  1243. case LACON:
  1244. assert(s->no != cnfa->pre);
  1245. ca->co = (color)(cnfa->ncolors + a->co);
  1246. ca->to = a->to->no;
  1247. ca++;
  1248. cnfa->flags |= HASLACONS;
  1249. break;
  1250. default:
  1251. assert(NOTREACHED);
  1252. break;
  1253. }
  1254. carcsort(first, ca-1);
  1255. ca->co = COLORLESS;
  1256. ca->to = 0;
  1257. ca++;
  1258. }
  1259. assert(ca == &cnfa->arcs[narcs]);
  1260. assert(cnfa->nstates != 0);
  1261. /* mark no-progress states */
  1262. for (a = nfa->pre->outs; a != NULL; a = a->outchain)
  1263. cnfa->states[a->to->no]->co = 1;
  1264. cnfa->states[nfa->pre->no]->co = 1;
  1265. }
  1266. /*
  1267.  - carcsort - sort compacted-NFA arcs by color
  1268.  * Really dumb algorithm, but if the list is long enough for that to matter,
  1269.  * you're in real trouble anyway.
  1270.  ^ static VOID carcsort(struct carc *, struct carc *);
  1271.  */
  1272. static VOID
  1273. carcsort(first, last)
  1274. struct carc *first;
  1275. struct carc *last;
  1276. {
  1277. struct carc *p;
  1278. struct carc *q;
  1279. struct carc tmp;
  1280. if (last - first <= 1)
  1281. return;
  1282. for (p = first; p <= last; p++)
  1283. for (q = p; q <= last; q++)
  1284. if (p->co > q->co ||
  1285. (p->co == q->co && p->to > q->to)) {
  1286. assert(p != q);
  1287. tmp = *p;
  1288. *p = *q;
  1289. *q = tmp;
  1290. }
  1291. }
  1292. /*
  1293.  - freecnfa - free a compacted NFA
  1294.  ^ static VOID freecnfa(struct cnfa *);
  1295.  */
  1296. static VOID
  1297. freecnfa(cnfa)
  1298. struct cnfa *cnfa;
  1299. {
  1300. assert(cnfa->nstates != 0); /* not empty already */
  1301. cnfa->nstates = 0;
  1302. FREE(cnfa->states);
  1303. FREE(cnfa->arcs);
  1304. }
  1305. /*
  1306.  - dumpnfa - dump an NFA in human-readable form
  1307.  ^ static VOID dumpnfa(struct nfa *, FILE *);
  1308.  */
  1309. static VOID
  1310. dumpnfa(nfa, f)
  1311. struct nfa *nfa;
  1312. FILE *f;
  1313. {
  1314. #ifdef REG_DEBUG
  1315. struct state *s;
  1316. fprintf(f, "pre %d, post %d", nfa->pre->no, nfa->post->no);
  1317. if (nfa->bos[0] != COLORLESS)
  1318. fprintf(f, ", bos [%ld]", (long)nfa->bos[0]);
  1319. if (nfa->bos[1] != COLORLESS)
  1320. fprintf(f, ", bol [%ld]", (long)nfa->bos[1]);
  1321. if (nfa->eos[0] != COLORLESS)
  1322. fprintf(f, ", eos [%ld]", (long)nfa->eos[0]);
  1323. if (nfa->eos[1] != COLORLESS)
  1324. fprintf(f, ", eol [%ld]", (long)nfa->eos[1]);
  1325. fprintf(f, "n");
  1326. for (s = nfa->states; s != NULL; s = s->next)
  1327. dumpstate(s, f);
  1328. if (nfa->parent == NULL)
  1329. dumpcolors(nfa->cm, f);
  1330. fflush(f);
  1331. #endif
  1332. }
  1333. #ifdef REG_DEBUG /* subordinates of dumpnfa */
  1334. /*
  1335.  ^ #ifdef REG_DEBUG
  1336.  */
  1337. /*
  1338.  - dumpstate - dump an NFA state in human-readable form
  1339.  ^ static VOID dumpstate(struct state *, FILE *);
  1340.  */
  1341. static VOID
  1342. dumpstate(s, f)
  1343. struct state *s;
  1344. FILE *f;
  1345. {
  1346. struct arc *a;
  1347. fprintf(f, "%d%s%c", s->no, (s->tmp != NULL) ? "T" : "",
  1348. (s->flag) ? s->flag : '.');
  1349. if (s->prev != NULL && s->prev->next != s)
  1350. fprintf(f, "tstate chain badn");
  1351. if (s->nouts == 0)
  1352. fprintf(f, "tno out arcsn");
  1353. else
  1354. dumparcs(s, f);
  1355. fflush(f);
  1356. for (a = s->ins; a != NULL; a = a->inchain) {
  1357. if (a->to != s)
  1358. fprintf(f, "tlink from %d to %d on %d's in-chainn",
  1359. a->from->no, a->to->no, s->no);
  1360. }
  1361. }
  1362. /*
  1363.  - dumparcs - dump out-arcs in human-readable form
  1364.  ^ static VOID dumparcs(struct state *, FILE *);
  1365.  */
  1366. static VOID
  1367. dumparcs(s, f)
  1368. struct state *s;
  1369. FILE *f;
  1370. {
  1371. int pos;
  1372. assert(s->nouts > 0);
  1373. /* printing arcs in reverse order is usually clearer */
  1374. pos = dumprarcs(s->outs, s, f, 1);
  1375. if (pos != 1)
  1376. fprintf(f, "n");
  1377. }
  1378. /*
  1379.  - dumprarcs - dump remaining outarcs, recursively, in reverse order
  1380.  ^ static int dumprarcs(struct arc *, struct state *, FILE *, int);
  1381.  */
  1382. static int /* resulting print position */
  1383. dumprarcs(a, s, f, pos)
  1384. struct arc *a;
  1385. struct state *s;
  1386. FILE *f;
  1387. int pos; /* initial print position */
  1388. {
  1389. if (a->outchain != NULL)
  1390. pos = dumprarcs(a->outchain, s, f, pos);
  1391. dumparc(a, s, f);
  1392. if (pos == 5) {
  1393. fprintf(f, "n");
  1394. pos = 1;
  1395. } else
  1396. pos++;
  1397. return pos;
  1398. }
  1399. /*
  1400.  - dumparc - dump one outarc in readable form, including prefixing tab
  1401.  ^ static VOID dumparc(struct arc *, struct state *, FILE *);
  1402.  */
  1403. static VOID
  1404. dumparc(a, s, f)
  1405. struct arc *a;
  1406. struct state *s;
  1407. FILE *f;
  1408. {
  1409. struct arc *aa;
  1410. struct arcbatch *ab;
  1411. fprintf(f, "t");
  1412. switch (a->type) {
  1413. case PLAIN:
  1414. fprintf(f, "[%ld]", (long)a->co);
  1415. break;
  1416. case AHEAD:
  1417. fprintf(f, ">%ld>", (long)a->co);
  1418. break;
  1419. case BEHIND:
  1420. fprintf(f, "<%ld<", (long)a->co);
  1421. break;
  1422. case LACON:
  1423. fprintf(f, ":%ld:", (long)a->co);
  1424. break;
  1425. case '^':
  1426. case '$':
  1427. fprintf(f, "%c%d", a->type, (int)a->co);
  1428. break;
  1429. case EMPTY:
  1430. break;
  1431. default:
  1432. fprintf(f, "0x%x/0%lo", a->type, (long)a->co);
  1433. break;
  1434. }
  1435. if (a->from != s)
  1436. fprintf(f, "?%d?", a->from->no);
  1437. for (ab = &a->from->oas; ab != NULL; ab = ab->next) {
  1438. for (aa = &ab->a[0]; aa < &ab->a[ABSIZE]; aa++)
  1439. if (aa == a)
  1440. break; /* NOTE BREAK OUT */
  1441. if (aa < &ab->a[ABSIZE]) /* propagate break */
  1442. break; /* NOTE BREAK OUT */
  1443. }
  1444. if (ab == NULL)
  1445. fprintf(f, "?!?"); /* not in allocated space */
  1446. fprintf(f, "->");
  1447. if (a->to == NULL) {
  1448. fprintf(f, "NULL");
  1449. return;
  1450. }
  1451. fprintf(f, "%d", a->to->no);
  1452. for (aa = a->to->ins; aa != NULL; aa = aa->inchain)
  1453. if (aa == a)
  1454. break; /* NOTE BREAK OUT */
  1455. if (aa == NULL)
  1456. fprintf(f, "?!?"); /* missing from in-chain */
  1457. }
  1458. /*
  1459.  ^ #endif
  1460.  */
  1461. #endif /* ifdef REG_DEBUG */
  1462. /*
  1463.  - dumpcnfa - dump a compacted NFA in human-readable form
  1464.  ^ static VOID dumpcnfa(struct cnfa *, FILE *);
  1465.  */
  1466. static VOID
  1467. dumpcnfa(cnfa, f)
  1468. struct cnfa *cnfa;
  1469. FILE *f;
  1470. {
  1471. #ifdef REG_DEBUG
  1472. int st;
  1473. fprintf(f, "pre %d, post %d", cnfa->pre, cnfa->post);
  1474. if (cnfa->bos[0] != COLORLESS)
  1475. fprintf(f, ", bos [%ld]", (long)cnfa->bos[0]);
  1476. if (cnfa->bos[1] != COLORLESS)
  1477. fprintf(f, ", bol [%ld]", (long)cnfa->bos[1]);
  1478. if (cnfa->eos[0] != COLORLESS)
  1479. fprintf(f, ", eos [%ld]", (long)cnfa->eos[0]);
  1480. if (cnfa->eos[1] != COLORLESS)
  1481. fprintf(f, ", eol [%ld]", (long)cnfa->eos[1]);
  1482. if (cnfa->flags&HASLACONS)
  1483. fprintf(f, ", haslacons");
  1484. fprintf(f, "n");
  1485. for (st = 0; st < cnfa->nstates; st++)
  1486. dumpcstate(st, cnfa->states[st], cnfa, f);
  1487. fflush(f);
  1488. #endif
  1489. }
  1490. #ifdef REG_DEBUG /* subordinates of dumpcnfa */
  1491. /*
  1492.  ^ #ifdef REG_DEBUG
  1493.  */
  1494. /*
  1495.  - dumpcstate - dump a compacted-NFA state in human-readable form
  1496.  ^ static VOID dumpcstate(int, struct carc *, struct cnfa *, FILE *);
  1497.  */
  1498. static VOID
  1499. dumpcstate(st, ca, cnfa, f)
  1500. int st;
  1501. struct carc *ca;
  1502. struct cnfa *cnfa;
  1503. FILE *f;
  1504. {
  1505. int i;
  1506. int pos;
  1507. fprintf(f, "%d%s", st, (ca[0].co) ? ":" : ".");
  1508. pos = 1;
  1509. for (i = 1; ca[i].co != COLORLESS; i++) {
  1510. if (ca[i].co < cnfa->ncolors)
  1511. fprintf(f, "t[%ld]->%d", (long)ca[i].co, ca[i].to);
  1512. else
  1513. fprintf(f, "t:%ld:->%d", (long)ca[i].co-cnfa->ncolors,
  1514. ca[i].to);
  1515. if (pos == 5) {
  1516. fprintf(f, "n");
  1517. pos = 1;
  1518. } else
  1519. pos++;
  1520. }
  1521. if (i == 1 || pos != 1)
  1522. fprintf(f, "n");
  1523. fflush(f);
  1524. }
  1525. /*
  1526.  ^ #endif
  1527.  */
  1528. #endif /* ifdef REG_DEBUG */