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

通讯编程

开发平台:

Visual C++

  1. /*
  2.  * colorings of characters
  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.  * Note that there are some incestuous relationships between this code and
  34.  * NFA arc maintenance, which perhaps ought to be cleaned up sometime.
  35.  */
  36. #define CISERR() VISERR(cm->v)
  37. #define CERR(e) VERR(cm->v, (e))
  38. /*
  39.  - initcm - set up new colormap
  40.  ^ static VOID initcm(struct vars *, struct colormap *);
  41.  */
  42. static VOID
  43. initcm(v, cm)
  44. struct vars *v;
  45. struct colormap *cm;
  46. {
  47. int i;
  48. int j;
  49. union tree *t;
  50. union tree *nextt;
  51. struct colordesc *cd;
  52. cm->magic = CMMAGIC;
  53. cm->v = v;
  54. cm->ncds = NINLINECDS;
  55. cm->cd = cm->cdspace;
  56. cm->max = 0;
  57. cm->free = 0;
  58. cd = cm->cd; /* cm->cd[WHITE] */
  59. cd->sub = NOSUB;
  60. cd->arcs = NULL;
  61. cd->flags = 0;
  62. cd->nchrs = CHR_MAX - CHR_MIN + 1;
  63. /* upper levels of tree */
  64. for (t = &cm->tree[0], j = NBYTS-1; j > 0; t = nextt, j--) {
  65. nextt = t + 1;
  66. for (i = BYTTAB-1; i >= 0; i--)
  67. t->tptr[i] = nextt;
  68. }
  69. /* bottom level is solid white */
  70. t = &cm->tree[NBYTS-1];
  71. for (i = BYTTAB-1; i >= 0; i--)
  72. t->tcolor[i] = WHITE;
  73. cd->block = t;
  74. }
  75. /*
  76.  - freecm - free dynamically-allocated things in a colormap
  77.  ^ static VOID freecm(struct colormap *);
  78.  */
  79. static VOID
  80. freecm(cm)
  81. struct colormap *cm;
  82. {
  83. size_t i;
  84. union tree *cb;
  85. cm->magic = 0;
  86. if (NBYTS > 1)
  87. cmtreefree(cm, cm->tree, 0);
  88. for (i = 1; i <= cm->max; i++) /* skip WHITE */
  89. if (!UNUSEDCOLOR(&cm->cd[i])) {
  90. cb = cm->cd[i].block;
  91. if (cb != NULL)
  92. FREE(cb);
  93. }
  94. if (cm->cd != cm->cdspace)
  95. FREE(cm->cd);
  96. }
  97. /*
  98.  - cmtreefree - free a non-terminal part of a colormap tree
  99.  ^ static VOID cmtreefree(struct colormap *, union tree *, int);
  100.  */
  101. static VOID
  102. cmtreefree(cm, tree, level)
  103. struct colormap *cm;
  104. union tree *tree;
  105. int level; /* level number (top == 0) of this block */
  106. {
  107. int i;
  108. union tree *t;
  109. union tree *fillt = &cm->tree[level+1];
  110. union tree *cb;
  111. assert(level < NBYTS-1); /* this level has pointers */
  112. for (i = BYTTAB-1; i >= 0; i--) {
  113. t = tree->tptr[i];
  114. assert(t != NULL);
  115. if (t != fillt) {
  116. if (level < NBYTS-2) { /* more pointer blocks below */
  117. cmtreefree(cm, t, level+1);
  118. FREE(t);
  119. } else { /* color block below */
  120. cb = cm->cd[t->tcolor[0]].block;
  121. if (t != cb) /* not a solid block */
  122. FREE(t);
  123. }
  124. }
  125. }
  126. }
  127. /*
  128.  - setcolor - set the color of a character in a colormap
  129.  ^ static color setcolor(struct colormap *, pchr, pcolor);
  130.  */
  131. static color /* previous color */
  132. setcolor(cm, c, co)
  133. struct colormap *cm;
  134. pchr c;
  135. pcolor co;
  136. {
  137. uchr uc = c;
  138. int shift;
  139. int level;
  140. int b;
  141. int bottom;
  142. union tree *t;
  143. union tree *newt;
  144. union tree *fillt;
  145. union tree *lastt;
  146. union tree *cb;
  147. color prev;
  148. assert(cm->magic == CMMAGIC);
  149. if (CISERR() || co == COLORLESS)
  150. return COLORLESS;
  151. t = cm->tree;
  152. for (level = 0, shift = BYTBITS * (NBYTS - 1); shift > 0;
  153. level++, shift -= BYTBITS) {
  154. b = (uc >> shift) & BYTMASK;
  155. lastt = t;
  156. t = lastt->tptr[b];
  157. assert(t != NULL);
  158. fillt = &cm->tree[level+1];
  159. bottom = (shift <= BYTBITS) ? 1 : 0;
  160. cb = (bottom) ? cm->cd[t->tcolor[0]].block : fillt;
  161. if (t == fillt || t == cb) { /* must allocate a new block */
  162. newt = (union tree *)MALLOC((bottom) ?
  163. sizeof(struct colors) : sizeof(struct ptrs));
  164. if (newt == NULL) {
  165. CERR(REG_ESPACE);
  166. return COLORLESS;
  167. }
  168. if (bottom)
  169. memcpy(VS(newt->tcolor), VS(t->tcolor),
  170. BYTTAB*sizeof(color));
  171. else
  172. memcpy(VS(newt->tptr), VS(t->tptr),
  173. BYTTAB*sizeof(union tree *));
  174. t = newt;
  175. lastt->tptr[b] = t;
  176. }
  177. }
  178. b = uc & BYTMASK;
  179. prev = t->tcolor[b];
  180. t->tcolor[b] = (color)co;
  181. return prev;
  182. }
  183. /*
  184.  - maxcolor - report largest color number in use
  185.  ^ static color maxcolor(struct colormap *);
  186.  */
  187. static color
  188. maxcolor(cm)
  189. struct colormap *cm;
  190. {
  191. if (CISERR())
  192. return COLORLESS;
  193. return (color)cm->max;
  194. }
  195. /*
  196.  - newcolor - find a new color (must be subject of setcolor at once)
  197.  * Beware:  may relocate the colordescs.
  198.  ^ static color newcolor(struct colormap *);
  199.  */
  200. static color /* COLORLESS for error */
  201. newcolor(cm)
  202. struct colormap *cm;
  203. {
  204. struct colordesc *cd;
  205. struct colordesc *new;
  206. size_t n;
  207. if (CISERR())
  208. return COLORLESS;
  209. if (cm->free != 0) {
  210. assert(cm->free > 0);
  211. assert((size_t)cm->free < cm->ncds);
  212. cd = &cm->cd[cm->free];
  213. assert(UNUSEDCOLOR(cd));
  214. assert(cd->arcs == NULL);
  215. cm->free = cd->sub;
  216. } else if (cm->max < cm->ncds - 1) {
  217. cm->max++;
  218. cd = &cm->cd[cm->max];
  219. } else {
  220. /* oops, must allocate more */
  221. n = cm->ncds * 2;
  222. if (cm->cd == cm->cdspace) {
  223. new = (struct colordesc *)MALLOC(n *
  224. sizeof(struct colordesc));
  225. if (new != NULL)
  226. memcpy(VS(new), VS(cm->cdspace), cm->ncds *
  227. sizeof(struct colordesc));
  228. } else
  229. new = (struct colordesc *)REALLOC(cm->cd,
  230. n * sizeof(struct colordesc));
  231. if (new == NULL) {
  232. CERR(REG_ESPACE);
  233. return COLORLESS;
  234. }
  235. cm->cd = new;
  236. cm->ncds = n;
  237. assert(cm->max < cm->ncds - 1);
  238. cm->max++;
  239. cd = &cm->cd[cm->max];
  240. }
  241. cd->nchrs = 0;
  242. cd->sub = NOSUB;
  243. cd->arcs = NULL;
  244. cd->flags = 0;
  245. cd->block = NULL;
  246. return (color)(cd - cm->cd);
  247. }
  248. /*
  249.  - freecolor - free a color (must have no arcs or subcolor)
  250.  ^ static VOID freecolor(struct colormap *, pcolor);
  251.  */
  252. static VOID
  253. freecolor(cm, co)
  254. struct colormap *cm;
  255. pcolor co;
  256. {
  257. struct colordesc *cd = &cm->cd[co];
  258. color pco, nco; /* for freelist scan */
  259. assert(co >= 0);
  260. if (co == WHITE)
  261. return;
  262. assert(cd->arcs == NULL);
  263. assert(cd->sub == NOSUB);
  264. assert(cd->nchrs == 0);
  265. cd->flags = FREECOL;
  266. if (cd->block != NULL) {
  267. FREE(cd->block);
  268. cd->block = NULL; /* just paranoia */
  269. }
  270. if ((size_t)co == cm->max) {
  271. while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max]))
  272. cm->max--;
  273. assert(cm->free >= 0);
  274. while ((size_t)cm->free > cm->max)
  275. cm->free = cm->cd[cm->free].sub;
  276. if (cm->free > 0) {
  277. assert(cm->free < cm->max);
  278. pco = cm->free;
  279. nco = cm->cd[pco].sub;
  280. while (nco > 0)
  281. if ((size_t)nco > cm->max) {
  282. /* take this one out of freelist */
  283. nco = cm->cd[nco].sub;
  284. cm->cd[pco].sub = nco;
  285. } else {
  286. assert(nco < cm->max);
  287. pco = nco;
  288. nco = cm->cd[pco].sub;
  289. }
  290. }
  291. } else {
  292. cd->sub = cm->free;
  293. cm->free = (color)(cd - cm->cd);
  294. }
  295. }
  296. /*
  297.  - pseudocolor - allocate a false color, to be managed by other means
  298.  ^ static color pseudocolor(struct colormap *);
  299.  */
  300. static color
  301. pseudocolor(cm)
  302. struct colormap *cm;
  303. {
  304. color co;
  305. co = newcolor(cm);
  306. if (CISERR())
  307. return COLORLESS;
  308. cm->cd[co].nchrs = 1;
  309. cm->cd[co].flags = PSEUDO;
  310. return co;
  311. }
  312. /*
  313.  - subcolor - allocate a new subcolor (if necessary) to this chr
  314.  ^ static color subcolor(struct colormap *, pchr c);
  315.  */
  316. static color
  317. subcolor(cm, c)
  318. struct colormap *cm;
  319. pchr c;
  320. {
  321. color co; /* current color of c */
  322. color sco; /* new subcolor */
  323. co = GETCOLOR(cm, c);
  324. sco = newsub(cm, co);
  325. if (CISERR())
  326. return COLORLESS;
  327. assert(sco != COLORLESS);
  328. if (co == sco) /* already in an open subcolor */
  329. return co; /* rest is redundant */
  330. cm->cd[co].nchrs--;
  331. cm->cd[sco].nchrs++;
  332. setcolor(cm, c, sco);
  333. return sco;
  334. }
  335. /*
  336.  - newsub - allocate a new subcolor (if necessary) for a color
  337.  ^ static color newsub(struct colormap *, pcolor);
  338.  */
  339. static color
  340. newsub(cm, co)
  341. struct colormap *cm;
  342. pcolor co;
  343. {
  344. color sco; /* new subcolor */
  345. sco = cm->cd[co].sub;
  346. if (sco == NOSUB) { /* color has no open subcolor */
  347. if (cm->cd[co].nchrs == 1) /* optimization */
  348. return co;
  349. sco = newcolor(cm); /* must create subcolor */
  350. if (sco == COLORLESS) {
  351. assert(CISERR());
  352. return COLORLESS;
  353. }
  354. cm->cd[co].sub = sco;
  355. cm->cd[sco].sub = sco; /* open subcolor points to self */
  356. }
  357. assert(sco != NOSUB);
  358. return sco;
  359. }
  360. /*
  361.  - subrange - allocate new subcolors to this range of chrs, fill in arcs
  362.  ^ static VOID subrange(struct vars *, pchr, pchr, struct state *,
  363.  ^  struct state *);
  364.  */
  365. static VOID
  366. subrange(v, from, to, lp, rp)
  367. struct vars *v;
  368. pchr from;
  369. pchr to;
  370. struct state *lp;
  371. struct state *rp;
  372. {
  373. uchr uf;
  374. int i;
  375. assert(from <= to);
  376. /* first, align "from" on a tree-block boundary */
  377. uf = (uchr)from;
  378. i = (int)( ((uf + BYTTAB-1) & (uchr)~BYTMASK) - uf );
  379. for (; from <= to && i > 0; i--, from++)
  380. newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
  381. if (from > to) /* didn't reach a boundary */
  382. return;
  383. /* deal with whole blocks */
  384. for (; to - from >= BYTTAB; from += BYTTAB)
  385. subblock(v, from, lp, rp);
  386. /* clean up any remaining partial table */
  387. for (; from <= to; from++)
  388. newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
  389. }
  390. /*
  391.  - subblock - allocate new subcolors for one tree block of chrs, fill in arcs
  392.  ^ static VOID subblock(struct vars *, pchr, struct state *, struct state *);
  393.  */
  394. static VOID
  395. subblock(v, start, lp, rp)
  396. struct vars *v;
  397. pchr start; /* first of BYTTAB chrs */
  398. struct state *lp;
  399. struct state *rp;
  400. {
  401. uchr uc = start;
  402. struct colormap *cm = v->cm;
  403. int shift;
  404. int level;
  405. int i;
  406. int b;
  407. union tree *t;
  408. union tree *cb;
  409. union tree *fillt;
  410. union tree *lastt;
  411. int previ;
  412. int ndone;
  413. color co;
  414. color sco;
  415. assert((uc % BYTTAB) == 0);
  416. /* find its color block, making new pointer blocks as needed */
  417. t = cm->tree;
  418. fillt = NULL;
  419. for (level = 0, shift = BYTBITS * (NBYTS - 1); shift > 0;
  420. level++, shift -= BYTBITS) {
  421. b = (uc >> shift) & BYTMASK;
  422. lastt = t;
  423. t = lastt->tptr[b];
  424. assert(t != NULL);
  425. fillt = &cm->tree[level+1];
  426. if (t == fillt && shift > BYTBITS) { /* need new ptr block */
  427. t = (union tree *)MALLOC(sizeof(struct ptrs));
  428. if (t == NULL) {
  429. CERR(REG_ESPACE);
  430. return;
  431. }
  432. memcpy(VS(t->tptr), VS(fillt->tptr),
  433. BYTTAB*sizeof(union tree *));
  434. lastt->tptr[b] = t;
  435. }
  436. }
  437. /* special cases:  fill block or solid block */
  438. co = t->tcolor[0];
  439. cb = cm->cd[co].block;
  440. if (t == fillt || t == cb) {
  441. /* either way, we want a subcolor solid block */
  442. sco = newsub(cm, co);
  443. t = cm->cd[sco].block;
  444. if (t == NULL) { /* must set it up */
  445. t = (union tree *)MALLOC(sizeof(struct colors));
  446. if (t == NULL) {
  447. CERR(REG_ESPACE);
  448. return;
  449. }
  450. for (i = 0; i < BYTTAB; i++)
  451. t->tcolor[i] = sco;
  452. cm->cd[sco].block = t;
  453. }
  454. /* find loop must have run at least once */
  455. lastt->tptr[b] = t;
  456. newarc(v->nfa, PLAIN, sco, lp, rp);
  457. cm->cd[co].nchrs -= BYTTAB;
  458. cm->cd[sco].nchrs += BYTTAB;
  459. return;
  460. }
  461. /* general case, a mixed block to be altered */
  462. i = 0;
  463. while (i < BYTTAB) {
  464. co = t->tcolor[i];
  465. sco = newsub(cm, co);
  466. newarc(v->nfa, PLAIN, sco, lp, rp);
  467. previ = i;
  468. do {
  469. t->tcolor[i++] = sco;
  470. } while (i < BYTTAB && t->tcolor[i] == co);
  471. ndone = i - previ;
  472. cm->cd[co].nchrs -= ndone;
  473. cm->cd[sco].nchrs += ndone;
  474. }
  475. }
  476. /*
  477.  - okcolors - promote subcolors to full colors
  478.  ^ static VOID okcolors(struct nfa *, struct colormap *);
  479.  */
  480. static VOID
  481. okcolors(nfa, cm)
  482. struct nfa *nfa;
  483. struct colormap *cm;
  484. {
  485. struct colordesc *cd;
  486. struct colordesc *end = CDEND(cm);
  487. struct colordesc *scd;
  488. struct arc *a;
  489. color co;
  490. color sco;
  491. for (cd = cm->cd, co = 0; cd < end; cd++, co++) {
  492. sco = cd->sub;
  493. if (UNUSEDCOLOR(cd) || sco == NOSUB) {
  494. /* has no subcolor, no further action */
  495. } else if (sco == co) {
  496. /* is subcolor, let parent deal with it */
  497. } else if (cd->nchrs == 0) {
  498. /* parent empty, its arcs change color to subcolor */
  499. cd->sub = NOSUB;
  500. scd = &cm->cd[sco];
  501. assert(scd->nchrs > 0);
  502. assert(scd->sub == sco);
  503. scd->sub = NOSUB;
  504. while ((a = cd->arcs) != NULL) {
  505. assert(a->co == co);
  506. uncolorchain(cm, a);
  507. a->co = sco;
  508. colorchain(cm, a);
  509. }
  510. freecolor(cm, co);
  511. } else {
  512. /* parent's arcs must gain parallel subcolor arcs */
  513. cd->sub = NOSUB;
  514. scd = &cm->cd[sco];
  515. assert(scd->nchrs > 0);
  516. assert(scd->sub == sco);
  517. scd->sub = NOSUB;
  518. for (a = cd->arcs; a != NULL; a = a->colorchain) {
  519. assert(a->co == co);
  520. newarc(nfa, a->type, sco, a->from, a->to);
  521. }
  522. }
  523. }
  524. }
  525. /*
  526.  - colorchain - add this arc to the color chain of its color
  527.  ^ static VOID colorchain(struct colormap *, struct arc *);
  528.  */
  529. static VOID
  530. colorchain(cm, a)
  531. struct colormap *cm;
  532. struct arc *a;
  533. {
  534. struct colordesc *cd = &cm->cd[a->co];
  535. if (cd->arcs)
  536. cd->arcs->colorchain_rev = a;
  537. a->colorchain = cd->arcs;
  538. a->colorchain_rev = NULL;
  539. cd->arcs = a;
  540. }
  541. /*
  542.  - uncolorchain - delete this arc from the color chain of its color
  543.  ^ static VOID uncolorchain(struct colormap *, struct arc *);
  544.  */
  545. static VOID
  546. uncolorchain(cm, a)
  547. struct colormap *cm;
  548. struct arc *a;
  549. {
  550. struct colordesc *cd = &cm->cd[a->co];
  551. struct arc *aa = a->colorchain_rev;
  552. if (aa == NULL) {
  553. assert(cd->arcs == a);
  554. cd->arcs = a->colorchain;
  555. } else {
  556. assert(aa->colorchain == a);
  557. aa->colorchain = a->colorchain;
  558. }
  559. if (a->colorchain)
  560. a->colorchain->colorchain_rev = aa;
  561. a->colorchain = NULL; /* paranoia */
  562. a->colorchain_rev = NULL;
  563. }
  564. /*
  565.  - singleton - is this character in its own color?
  566.  ^ static int singleton(struct colormap *, pchr c);
  567.  */
  568. static int /* predicate */
  569. singleton(cm, c)
  570. struct colormap *cm;
  571. pchr c;
  572. {
  573. color co; /* color of c */
  574. co = GETCOLOR(cm, c);
  575. if (cm->cd[co].nchrs == 1 && cm->cd[co].sub == NOSUB)
  576. return 1;
  577. return 0;
  578. }
  579. /*
  580.  - rainbow - add arcs of all full colors (but one) between specified states
  581.  ^ static VOID rainbow(struct nfa *, struct colormap *, int, pcolor,
  582.  ^  struct state *, struct state *);
  583.  */
  584. static VOID
  585. rainbow(nfa, cm, type, but, from, to)
  586. struct nfa *nfa;
  587. struct colormap *cm;
  588. int type;
  589. pcolor but; /* COLORLESS if no exceptions */
  590. struct state *from;
  591. struct state *to;
  592. {
  593. struct colordesc *cd;
  594. struct colordesc *end = CDEND(cm);
  595. color co;
  596. for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
  597. if (!UNUSEDCOLOR(cd) && cd->sub != co && co != but &&
  598. !(cd->flags&PSEUDO))
  599. newarc(nfa, type, co, from, to);
  600. }
  601. /*
  602.  - colorcomplement - add arcs of complementary colors
  603.  * The calling sequence ought to be reconciled with cloneouts().
  604.  ^ static VOID colorcomplement(struct nfa *, struct colormap *, int,
  605.  ^  struct state *, struct state *, struct state *);
  606.  */
  607. static VOID
  608. colorcomplement(nfa, cm, type, of, from, to)
  609. struct nfa *nfa;
  610. struct colormap *cm;
  611. int type;
  612. struct state *of; /* complements of this guy's PLAIN outarcs */
  613. struct state *from;
  614. struct state *to;
  615. {
  616. struct colordesc *cd;
  617. struct colordesc *end = CDEND(cm);
  618. color co;
  619. assert(of != from);
  620. for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
  621. if (!UNUSEDCOLOR(cd) && !(cd->flags&PSEUDO))
  622. if (findarc(of, PLAIN, co) == NULL)
  623. newarc(nfa, type, co, from, to);
  624. }
  625. #ifdef REG_DEBUG
  626. /*
  627.  ^ #ifdef REG_DEBUG
  628.  */
  629. /*
  630.  - dumpcolors - debugging output
  631.  ^ static VOID dumpcolors(struct colormap *, FILE *);
  632.  */
  633. static VOID
  634. dumpcolors(cm, f)
  635. struct colormap *cm;
  636. FILE *f;
  637. {
  638. struct colordesc *cd;
  639. struct colordesc *end;
  640. color co;
  641. chr c;
  642. char *has;
  643. fprintf(f, "max %ldn", (long)cm->max);
  644. if (NBYTS > 1)
  645. fillcheck(cm, cm->tree, 0, f);
  646. end = CDEND(cm);
  647. for (cd = cm->cd + 1, co = 1; cd < end; cd++, co++) /* skip 0 */
  648. if (!UNUSEDCOLOR(cd)) {
  649. assert(cd->nchrs > 0);
  650. has = (cd->block != NULL) ? "#" : "";
  651. if (cd->flags&PSEUDO)
  652. fprintf(f, "#%2ld%s(ps): ", (long)co, has);
  653. else
  654. fprintf(f, "#%2ld%s(%2d): ", (long)co,
  655. has, cd->nchrs);
  656. /* it's hard to do this more efficiently */
  657. for (c = CHR_MIN; c < CHR_MAX; c++)
  658. if (GETCOLOR(cm, c) == co)
  659. dumpchr(c, f);
  660. assert(c == CHR_MAX);
  661. if (GETCOLOR(cm, c) == co)
  662. dumpchr(c, f);
  663. fprintf(f, "n");
  664. }
  665. }
  666. /*
  667.  - fillcheck - check proper filling of a tree
  668.  ^ static VOID fillcheck(struct colormap *, union tree *, int, FILE *);
  669.  */
  670. static VOID
  671. fillcheck(cm, tree, level, f)
  672. struct colormap *cm;
  673. union tree *tree;
  674. int level; /* level number (top == 0) of this block */
  675. FILE *f;
  676. {
  677. int i;
  678. union tree *t;
  679. union tree *fillt = &cm->tree[level+1];
  680. assert(level < NBYTS-1); /* this level has pointers */
  681. for (i = BYTTAB-1; i >= 0; i--) {
  682. t = tree->tptr[i];
  683. if (t == NULL)
  684. fprintf(f, "NULL found in filled tree!n");
  685. else if (t == fillt)
  686. {}
  687. else if (level < NBYTS-2) /* more pointer blocks below */
  688. fillcheck(cm, t, level+1, f);
  689. }
  690. }
  691. /*
  692.  - dumpchr - print a chr
  693.  * Kind of char-centric but works well enough for debug use.
  694.  ^ static VOID dumpchr(pchr, FILE *);
  695.  */
  696. static VOID
  697. dumpchr(c, f)
  698. pchr c;
  699. FILE *f;
  700. {
  701. if (c == '\')
  702. fprintf(f, "\\");
  703. else if (c > ' ' && c <= '~')
  704. putc((char)c, f);
  705. else
  706. fprintf(f, "\u%04lx", (long)c);
  707. }
  708. /*
  709.  ^ #endif
  710.  */
  711. #endif /* ifdef REG_DEBUG */