regc_color.cGo to the documentation of this file.00001 /* 00002 * colorings of characters 00003 * This file is #included by regcomp.c. 00004 * 00005 * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved. 00006 * 00007 * Development of this software was funded, in part, by Cray Research Inc., 00008 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics 00009 * Corporation, none of whom are responsible for the results. The author 00010 * thanks all of them. 00011 * 00012 * Redistribution and use in source and binary forms -- with or without 00013 * modification -- are permitted for any purpose, provided that 00014 * redistributions in source form retain this entire copyright notice and 00015 * indicate the origin and nature of any modifications. 00016 * 00017 * I'd appreciate being given credit for this package in the documentation of 00018 * software which uses it, but that is not a requirement. 00019 * 00020 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 00021 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 00022 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 00023 * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 * 00031 * Note that there are some incestuous relationships between this code and NFA 00032 * arc maintenance, which perhaps ought to be cleaned up sometime. 00033 */ 00034 00035 #define CISERR() VISERR(cm->v) 00036 #define CERR(e) VERR(cm->v, (e)) 00037 00038 /* 00039 - initcm - set up new colormap 00040 ^ static VOID initcm(struct vars *, struct colormap *); 00041 */ 00042 static void 00043 initcm( 00044 struct vars *v, 00045 struct colormap *cm) 00046 { 00047 int i; 00048 int j; 00049 union tree *t; 00050 union tree *nextt; 00051 struct colordesc *cd; 00052 00053 cm->magic = CMMAGIC; 00054 cm->v = v; 00055 00056 cm->ncds = NINLINECDS; 00057 cm->cd = cm->cdspace; 00058 cm->max = 0; 00059 cm->free = 0; 00060 00061 cd = cm->cd; /* cm->cd[WHITE] */ 00062 cd->sub = NOSUB; 00063 cd->arcs = NULL; 00064 cd->flags = 0; 00065 cd->nchrs = CHR_MAX - CHR_MIN + 1; 00066 00067 /* 00068 * Upper levels of tree. 00069 */ 00070 00071 for (t=&cm->tree[0], j=NBYTS-1 ; j>0 ; t=nextt, j--) { 00072 nextt = t + 1; 00073 for (i=BYTTAB-1 ; i>=0 ; i--) { 00074 t->tptr[i] = nextt; 00075 } 00076 } 00077 00078 /* 00079 * Bottom level is solid white. 00080 */ 00081 00082 t = &cm->tree[NBYTS-1]; 00083 for (i=BYTTAB-1 ; i>=0 ; i--) { 00084 t->tcolor[i] = WHITE; 00085 } 00086 cd->block = t; 00087 } 00088 00089 /* 00090 - freecm - free dynamically-allocated things in a colormap 00091 ^ static VOID freecm(struct colormap *); 00092 */ 00093 static void 00094 freecm( 00095 struct colormap *cm) 00096 { 00097 size_t i; 00098 union tree *cb; 00099 00100 cm->magic = 0; 00101 if (NBYTS > 1) { 00102 cmtreefree(cm, cm->tree, 0); 00103 } 00104 for (i=1 ; i<=cm->max ; i++) { /* skip WHITE */ 00105 if (!UNUSEDCOLOR(&cm->cd[i])) { 00106 cb = cm->cd[i].block; 00107 if (cb != NULL) { 00108 FREE(cb); 00109 } 00110 } 00111 } 00112 if (cm->cd != cm->cdspace) { 00113 FREE(cm->cd); 00114 } 00115 } 00116 00117 /* 00118 - cmtreefree - free a non-terminal part of a colormap tree 00119 ^ static VOID cmtreefree(struct colormap *, union tree *, int); 00120 */ 00121 static void 00122 cmtreefree( 00123 struct colormap *cm, 00124 union tree *tree, 00125 int level) /* level number (top == 0) of this block */ 00126 { 00127 int i; 00128 union tree *t; 00129 union tree *fillt = &cm->tree[level+1]; 00130 union tree *cb; 00131 00132 assert(level < NBYTS-1); /* this level has pointers */ 00133 for (i=BYTTAB-1 ; i>=0 ; i--) { 00134 t = tree->tptr[i]; 00135 assert(t != NULL); 00136 if (t != fillt) { 00137 if (level < NBYTS-2) { /* more pointer blocks below */ 00138 cmtreefree(cm, t, level+1); 00139 FREE(t); 00140 } else { /* color block below */ 00141 cb = cm->cd[t->tcolor[0]].block; 00142 if (t != cb) { /* not a solid block */ 00143 FREE(t); 00144 } 00145 } 00146 } 00147 } 00148 } 00149 00150 /* 00151 - setcolor - set the color of a character in a colormap 00152 ^ static color setcolor(struct colormap *, pchr, pcolor); 00153 */ 00154 static color /* previous color */ 00155 setcolor( 00156 struct colormap *cm, 00157 pchr c, 00158 pcolor co) 00159 { 00160 uchr uc = c; 00161 int shift; 00162 int level; 00163 int b; 00164 int bottom; 00165 union tree *t; 00166 union tree *newt; 00167 union tree *fillt; 00168 union tree *lastt; 00169 union tree *cb; 00170 color prev; 00171 00172 assert(cm->magic == CMMAGIC); 00173 if (CISERR() || co == COLORLESS) { 00174 return COLORLESS; 00175 } 00176 00177 t = cm->tree; 00178 for (level=0, shift=BYTBITS*(NBYTS-1) ; shift>0; level++, shift-=BYTBITS){ 00179 b = (uc >> shift) & BYTMASK; 00180 lastt = t; 00181 t = lastt->tptr[b]; 00182 assert(t != NULL); 00183 fillt = &cm->tree[level+1]; 00184 bottom = (shift <= BYTBITS) ? 1 : 0; 00185 cb = (bottom) ? cm->cd[t->tcolor[0]].block : fillt; 00186 if (t == fillt || t == cb) { /* must allocate a new block */ 00187 newt = (union tree *) MALLOC((bottom) ? 00188 sizeof(struct colors) : sizeof(struct ptrs)); 00189 if (newt == NULL) { 00190 CERR(REG_ESPACE); 00191 return COLORLESS; 00192 } 00193 if (bottom) { 00194 memcpy(newt->tcolor, t->tcolor, BYTTAB*sizeof(color)); 00195 } else { 00196 memcpy(newt->tptr, t->tptr, BYTTAB*sizeof(union tree *)); 00197 } 00198 t = newt; 00199 lastt->tptr[b] = t; 00200 } 00201 } 00202 00203 b = uc & BYTMASK; 00204 prev = t->tcolor[b]; 00205 t->tcolor[b] = (color) co; 00206 return prev; 00207 } 00208 00209 /* 00210 - maxcolor - report largest color number in use 00211 ^ static color maxcolor(struct colormap *); 00212 */ 00213 static color 00214 maxcolor( 00215 struct colormap *cm) 00216 { 00217 if (CISERR()) { 00218 return COLORLESS; 00219 } 00220 00221 return (color) cm->max; 00222 } 00223 00224 /* 00225 - newcolor - find a new color (must be subject of setcolor at once) 00226 * Beware: may relocate the colordescs. 00227 ^ static color newcolor(struct colormap *); 00228 */ 00229 static color /* COLORLESS for error */ 00230 newcolor( 00231 struct colormap *cm) 00232 { 00233 struct colordesc *cd; 00234 size_t n; 00235 00236 if (CISERR()) { 00237 return COLORLESS; 00238 } 00239 00240 if (cm->free != 0) { 00241 assert(cm->free > 0); 00242 assert((size_t) cm->free < cm->ncds); 00243 cd = &cm->cd[cm->free]; 00244 assert(UNUSEDCOLOR(cd)); 00245 assert(cd->arcs == NULL); 00246 cm->free = cd->sub; 00247 } else if (cm->max < cm->ncds - 1) { 00248 cm->max++; 00249 cd = &cm->cd[cm->max]; 00250 } else { 00251 struct colordesc *newCd; 00252 00253 /* 00254 * Oops, must allocate more. 00255 */ 00256 00257 n = cm->ncds * 2; 00258 if (cm->cd == cm->cdspace) { 00259 newCd = (struct colordesc *) MALLOC(n * sizeof(struct colordesc)); 00260 if (newCd != NULL) { 00261 memcpy(newCd, cm->cdspace, 00262 cm->ncds * sizeof(struct colordesc)); 00263 } 00264 } else { 00265 newCd = (struct colordesc *) 00266 REALLOC(cm->cd, n * sizeof(struct colordesc)); 00267 } 00268 if (newCd == NULL) { 00269 CERR(REG_ESPACE); 00270 return COLORLESS; 00271 } 00272 cm->cd = newCd; 00273 cm->ncds = n; 00274 assert(cm->max < cm->ncds - 1); 00275 cm->max++; 00276 cd = &cm->cd[cm->max]; 00277 } 00278 00279 cd->nchrs = 0; 00280 cd->sub = NOSUB; 00281 cd->arcs = NULL; 00282 cd->flags = 0; 00283 cd->block = NULL; 00284 00285 return (color) (cd - cm->cd); 00286 } 00287 00288 /* 00289 - freecolor - free a color (must have no arcs or subcolor) 00290 ^ static VOID freecolor(struct colormap *, pcolor); 00291 */ 00292 static void 00293 freecolor( 00294 struct colormap *cm, 00295 pcolor co) 00296 { 00297 struct colordesc *cd = &cm->cd[co]; 00298 color pco, nco; /* for freelist scan */ 00299 00300 assert(co >= 0); 00301 if (co == WHITE) { 00302 return; 00303 } 00304 00305 assert(cd->arcs == NULL); 00306 assert(cd->sub == NOSUB); 00307 assert(cd->nchrs == 0); 00308 cd->flags = FREECOL; 00309 if (cd->block != NULL) { 00310 FREE(cd->block); 00311 cd->block = NULL; /* just paranoia */ 00312 } 00313 00314 if ((size_t) co == cm->max) { 00315 while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max])) { 00316 cm->max--; 00317 } 00318 assert(cm->free >= 0); 00319 while ((size_t) cm->free > cm->max) { 00320 cm->free = cm->cd[cm->free].sub; 00321 } 00322 if (cm->free > 0) { 00323 assert(cm->free < cm->max); 00324 pco = cm->free; 00325 nco = cm->cd[pco].sub; 00326 while (nco > 0) { 00327 if ((size_t) nco > cm->max) { 00328 /* 00329 * Take this one out of freelist. 00330 */ 00331 00332 nco = cm->cd[nco].sub; 00333 cm->cd[pco].sub = nco; 00334 } else { 00335 assert(nco < cm->max); 00336 pco = nco; 00337 nco = cm->cd[pco].sub; 00338 } 00339 } 00340 } 00341 } else { 00342 cd->sub = cm->free; 00343 cm->free = (color) (cd - cm->cd); 00344 } 00345 } 00346 00347 /* 00348 - pseudocolor - allocate a false color, to be managed by other means 00349 ^ static color pseudocolor(struct colormap *); 00350 */ 00351 static color 00352 pseudocolor( 00353 struct colormap *cm) 00354 { 00355 color co; 00356 00357 co = newcolor(cm); 00358 if (CISERR()) { 00359 return COLORLESS; 00360 } 00361 cm->cd[co].nchrs = 1; 00362 cm->cd[co].flags = PSEUDO; 00363 return co; 00364 } 00365 00366 /* 00367 - subcolor - allocate a new subcolor (if necessary) to this chr 00368 ^ static color subcolor(struct colormap *, pchr c); 00369 */ 00370 static color 00371 subcolor( 00372 struct colormap *cm, 00373 pchr c) 00374 { 00375 color co; /* current color of c */ 00376 color sco; /* new subcolor */ 00377 00378 co = GETCOLOR(cm, c); 00379 sco = newsub(cm, co); 00380 if (CISERR()) { 00381 return COLORLESS; 00382 } 00383 assert(sco != COLORLESS); 00384 00385 if (co == sco) { /* already in an open subcolor */ 00386 return co; /* rest is redundant */ 00387 } 00388 cm->cd[co].nchrs--; 00389 cm->cd[sco].nchrs++; 00390 setcolor(cm, c, sco); 00391 return sco; 00392 } 00393 00394 /* 00395 - newsub - allocate a new subcolor (if necessary) for a color 00396 ^ static color newsub(struct colormap *, pcolor); 00397 */ 00398 static color 00399 newsub( 00400 struct colormap *cm, 00401 pcolor co) 00402 { 00403 color sco; /* new subcolor */ 00404 00405 sco = cm->cd[co].sub; 00406 if (sco == NOSUB) { /* color has no open subcolor */ 00407 if (cm->cd[co].nchrs == 1) { /* optimization */ 00408 return co; 00409 } 00410 sco = newcolor(cm); /* must create subcolor */ 00411 if (sco == COLORLESS) { 00412 assert(CISERR()); 00413 return COLORLESS; 00414 } 00415 cm->cd[co].sub = sco; 00416 cm->cd[sco].sub = sco; /* open subcolor points to self */ 00417 } 00418 assert(sco != NOSUB); 00419 00420 return sco; 00421 } 00422 00423 /* 00424 - subrange - allocate new subcolors to this range of chrs, fill in arcs 00425 ^ static VOID subrange(struct vars *, pchr, pchr, struct state *, 00426 ^ struct state *); 00427 */ 00428 static void 00429 subrange( 00430 struct vars *v, 00431 pchr from, 00432 pchr to, 00433 struct state *lp, 00434 struct state *rp) 00435 { 00436 uchr uf; 00437 int i; 00438 00439 assert(from <= to); 00440 00441 /* 00442 * First, align "from" on a tree-block boundary 00443 */ 00444 00445 uf = (uchr) from; 00446 i = (int) (((uf + BYTTAB - 1) & (uchr) ~BYTMASK) - uf); 00447 for (; from<=to && i>0; i--, from++) { 00448 newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp); 00449 } 00450 if (from > to) { /* didn't reach a boundary */ 00451 return; 00452 } 00453 00454 /* 00455 * Deal with whole blocks. 00456 */ 00457 00458 for (; to-from>=BYTTAB ; from+=BYTTAB) { 00459 subblock(v, from, lp, rp); 00460 } 00461 00462 /* 00463 * Clean up any remaining partial table. 00464 */ 00465 00466 for (; from<=to ; from++) { 00467 newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp); 00468 } 00469 } 00470 00471 /* 00472 - subblock - allocate new subcolors for one tree block of chrs, fill in arcs 00473 ^ static VOID subblock(struct vars *, pchr, struct state *, struct state *); 00474 */ 00475 static void 00476 subblock( 00477 struct vars *v, 00478 pchr start, /* first of BYTTAB chrs */ 00479 struct state *lp, 00480 struct state *rp) 00481 { 00482 uchr uc = start; 00483 struct colormap *cm = v->cm; 00484 int shift; 00485 int level; 00486 int i; 00487 int b; 00488 union tree *t; 00489 union tree *cb; 00490 union tree *fillt; 00491 union tree *lastt; 00492 int previ; 00493 int ndone; 00494 color co; 00495 color sco; 00496 00497 assert((uc % BYTTAB) == 0); 00498 00499 /* 00500 * Find its color block, making new pointer blocks as needed. 00501 */ 00502 00503 t = cm->tree; 00504 fillt = NULL; 00505 for (level=0, shift=BYTBITS*(NBYTS-1); shift>0; level++, shift-=BYTBITS) { 00506 b = (uc >> shift) & BYTMASK; 00507 lastt = t; 00508 t = lastt->tptr[b]; 00509 assert(t != NULL); 00510 fillt = &cm->tree[level+1]; 00511 if (t == fillt && shift > BYTBITS) { /* need new ptr block */ 00512 t = (union tree *) MALLOC(sizeof(struct ptrs)); 00513 if (t == NULL) { 00514 CERR(REG_ESPACE); 00515 return; 00516 } 00517 memcpy(t->tptr, fillt->tptr, BYTTAB*sizeof(union tree *)); 00518 lastt->tptr[b] = t; 00519 } 00520 } 00521 00522 /* 00523 * Special cases: fill block or solid block. 00524 */ 00525 co = t->tcolor[0]; 00526 cb = cm->cd[co].block; 00527 if (t == fillt || t == cb) { 00528 /* 00529 * Either way, we want a subcolor solid block. 00530 */ 00531 00532 sco = newsub(cm, co); 00533 t = cm->cd[sco].block; 00534 if (t == NULL) { /* must set it up */ 00535 t = (union tree *) MALLOC(sizeof(struct colors)); 00536 if (t == NULL) { 00537 CERR(REG_ESPACE); 00538 return; 00539 } 00540 for (i=0 ; i<BYTTAB ; i++) { 00541 t->tcolor[i] = sco; 00542 } 00543 cm->cd[sco].block = t; 00544 } 00545 00546 /* 00547 * Find loop must have run at least once. 00548 */ 00549 00550 lastt->tptr[b] = t; 00551 newarc(v->nfa, PLAIN, sco, lp, rp); 00552 cm->cd[co].nchrs -= BYTTAB; 00553 cm->cd[sco].nchrs += BYTTAB; 00554 return; 00555 } 00556 00557 /* 00558 * General case, a mixed block to be altered. 00559 */ 00560 00561 i = 0; 00562 while (i < BYTTAB) { 00563 co = t->tcolor[i]; 00564 sco = newsub(cm, co); 00565 newarc(v->nfa, PLAIN, sco, lp, rp); 00566 previ = i; 00567 do { 00568 t->tcolor[i++] = sco; 00569 } while (i < BYTTAB && t->tcolor[i] == co); 00570 ndone = i - previ; 00571 cm->cd[co].nchrs -= ndone; 00572 cm->cd[sco].nchrs += ndone; 00573 } 00574 } 00575 00576 /* 00577 - okcolors - promote subcolors to full colors 00578 ^ static VOID okcolors(struct nfa *, struct colormap *); 00579 */ 00580 static void 00581 okcolors( 00582 struct nfa *nfa, 00583 struct colormap *cm) 00584 { 00585 struct colordesc *cd; 00586 struct colordesc *end = CDEND(cm); 00587 struct colordesc *scd; 00588 struct arc *a; 00589 color co; 00590 color sco; 00591 00592 for (cd=cm->cd, co=0 ; cd<end ; cd++, co++) { 00593 sco = cd->sub; 00594 if (UNUSEDCOLOR(cd) || sco == NOSUB) { 00595 /* 00596 * Has no subcolor, no further action. 00597 */ 00598 } else if (sco == co) { 00599 /* 00600 * Is subcolor, let parent deal with it. 00601 */ 00602 } else if (cd->nchrs == 0) { 00603 /* 00604 * Parent empty, its arcs change color to subcolor. 00605 */ 00606 00607 cd->sub = NOSUB; 00608 scd = &cm->cd[sco]; 00609 assert(scd->nchrs > 0); 00610 assert(scd->sub == sco); 00611 scd->sub = NOSUB; 00612 while ((a = cd->arcs) != NULL) { 00613 assert(a->co == co); 00614 uncolorchain(cm, a); 00615 a->co = sco; 00616 colorchain(cm, a); 00617 } 00618 freecolor(cm, co); 00619 } else { 00620 /* 00621 * Parent's arcs must gain parallel subcolor arcs. 00622 */ 00623 00624 cd->sub = NOSUB; 00625 scd = &cm->cd[sco]; 00626 assert(scd->nchrs > 0); 00627 assert(scd->sub == sco); 00628 scd->sub = NOSUB; 00629 for (a=cd->arcs ; a!=NULL ; a=a->colorchain) { 00630 assert(a->co == co); 00631 newarc(nfa, a->type, sco, a->from, a->to); 00632 } 00633 } 00634 } 00635 } 00636 00637 /* 00638 - colorchain - add this arc to the color chain of its color 00639 ^ static VOID colorchain(struct colormap *, struct arc *); 00640 */ 00641 static void 00642 colorchain( 00643 struct colormap *cm, 00644 struct arc *a) 00645 { 00646 struct colordesc *cd = &cm->cd[a->co]; 00647 00648 if (cd->arcs != NULL) { 00649 cd->arcs->colorchainRev = a; 00650 } 00651 a->colorchain = cd->arcs; 00652 a->colorchainRev = NULL; 00653 cd->arcs = a; 00654 } 00655 00656 /* 00657 - uncolorchain - delete this arc from the color chain of its color 00658 ^ static VOID uncolorchain(struct colormap *, struct arc *); 00659 */ 00660 static void 00661 uncolorchain( 00662 struct colormap *cm, 00663 struct arc *a) 00664 { 00665 struct colordesc *cd = &cm->cd[a->co]; 00666 struct arc *aa = a->colorchainRev; 00667 00668 if (aa == NULL) { 00669 assert(cd->arcs == a); 00670 cd->arcs = a->colorchain; 00671 } else { 00672 assert(aa->colorchain == a); 00673 aa->colorchain = a->colorchain; 00674 } 00675 if (a->colorchain != NULL) { 00676 a->colorchain->colorchainRev = aa; 00677 } 00678 a->colorchain = NULL; /* paranoia */ 00679 a->colorchainRev = NULL; 00680 } 00681 00682 /* 00683 - rainbow - add arcs of all full colors (but one) between specified states 00684 ^ static VOID rainbow(struct nfa *, struct colormap *, int, pcolor, 00685 ^ struct state *, struct state *); 00686 */ 00687 static void 00688 rainbow( 00689 struct nfa *nfa, 00690 struct colormap *cm, 00691 int type, 00692 pcolor but, /* COLORLESS if no exceptions */ 00693 struct state *from, 00694 struct state *to) 00695 { 00696 struct colordesc *cd; 00697 struct colordesc *end = CDEND(cm); 00698 color co; 00699 00700 for (cd=cm->cd, co=0 ; cd<end && !CISERR(); cd++, co++) { 00701 if (!UNUSEDCOLOR(cd) && (cd->sub != co) && (co != but) 00702 && !(cd->flags&PSEUDO)) { 00703 newarc(nfa, type, co, from, to); 00704 } 00705 } 00706 } 00707 00708 /* 00709 - colorcomplement - add arcs of complementary colors 00710 * The calling sequence ought to be reconciled with cloneouts(). 00711 ^ static VOID colorcomplement(struct nfa *, struct colormap *, int, 00712 ^ struct state *, struct state *, struct state *); 00713 */ 00714 static void 00715 colorcomplement( 00716 struct nfa *nfa, 00717 struct colormap *cm, 00718 int type, 00719 struct state *of, /* complements of this guy's PLAIN outarcs */ 00720 struct state *from, 00721 struct state *to) 00722 { 00723 struct colordesc *cd; 00724 struct colordesc *end = CDEND(cm); 00725 color co; 00726 00727 assert(of != from); 00728 for (cd=cm->cd, co=0 ; cd<end && !CISERR() ; cd++, co++) { 00729 if (!UNUSEDCOLOR(cd) && !(cd->flags&PSEUDO)) { 00730 if (findarc(of, PLAIN, co) == NULL) { 00731 newarc(nfa, type, co, from, to); 00732 } 00733 } 00734 } 00735 } 00736 00737 #ifdef REG_DEBUG 00738 /* 00739 ^ #ifdef REG_DEBUG 00740 */ 00741 00742 /* 00743 - dumpcolors - debugging output 00744 ^ static VOID dumpcolors(struct colormap *, FILE *); 00745 */ 00746 static void 00747 dumpcolors( 00748 struct colormap *cm, 00749 FILE *f) 00750 { 00751 struct colordesc *cd; 00752 struct colordesc *end; 00753 color co; 00754 chr c; 00755 char *has; 00756 00757 fprintf(f, "max %ld\n", (long) cm->max); 00758 if (NBYTS > 1) { 00759 fillcheck(cm, cm->tree, 0, f); 00760 } 00761 end = CDEND(cm); 00762 for (cd=cm->cd+1, co=1 ; cd<end ; cd++, co++) { /* skip 0 */ 00763 if (!UNUSEDCOLOR(cd)) { 00764 assert(cd->nchrs > 0); 00765 has = (cd->block != NULL) ? "#" : ""; 00766 if (cd->flags&PSEUDO) { 00767 fprintf(f, "#%2ld%s(ps): ", (long) co, has); 00768 } else { 00769 fprintf(f, "#%2ld%s(%2d): ", (long) co, has, cd->nchrs); 00770 } 00771 00772 /* 00773 * It's hard to do this more efficiently. 00774 */ 00775 00776 for (c=CHR_MIN ; c<CHR_MAX ; c++) { 00777 if (GETCOLOR(cm, c) == co) { 00778 dumpchr(c, f); 00779 } 00780 } 00781 assert(c == CHR_MAX); 00782 if (GETCOLOR(cm, c) == co) { 00783 dumpchr(c, f); 00784 } 00785 fprintf(f, "\n"); 00786 } 00787 } 00788 } 00789 00790 /* 00791 - fillcheck - check proper filling of a tree 00792 ^ static VOID fillcheck(struct colormap *, union tree *, int, FILE *); 00793 */ 00794 static void 00795 fillcheck( 00796 struct colormap *cm, 00797 union tree *tree, 00798 int level, /* level number (top == 0) of this block */ 00799 FILE *f) 00800 { 00801 int i; 00802 union tree *t; 00803 union tree *fillt = &cm->tree[level+1]; 00804 00805 assert(level < NBYTS-1); /* this level has pointers */ 00806 for (i=BYTTAB-1 ; i>=0 ; i--) { 00807 t = tree->tptr[i]; 00808 if (t == NULL) { 00809 fprintf(f, "NULL found in filled tree!\n"); 00810 } else if (t == fillt) { 00811 /* empty body */ 00812 } else if (level < NBYTS-2) { /* more pointer blocks below */ 00813 fillcheck(cm, t, level+1, f); 00814 } 00815 } 00816 } 00817 00818 /* 00819 - dumpchr - print a chr 00820 * Kind of char-centric but works well enough for debug use. 00821 ^ static VOID dumpchr(pchr, FILE *); 00822 */ 00823 static void 00824 dumpchr( 00825 pchr c, 00826 FILE *f) 00827 { 00828 if (c == '\\') { 00829 fprintf(f, "\\\\"); 00830 } else if (c > ' ' && c <= '~') { 00831 putc((char) c, f); 00832 } else { 00833 fprintf(f, "\\u%04lx", (long) c); 00834 } 00835 } 00836 00837 /* 00838 ^ #endif 00839 */ 00840 #endif /* ifdef REG_DEBUG */ 00841 00842 /* 00843 * Local Variables: 00844 * mode: c 00845 * c-basic-offset: 4 00846 * fill-column: 78 00847 * End: 00848 */
Generated on Wed Mar 12 12:18:10 2008 by 1.5.1 |