regc_color.c

Go 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  doxygen 1.5.1