LCOV - code coverage report
Current view: top level - src/backend/regex - regc_color.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 259 456 56.8 %
Date: 2017-09-29 13:40:31 Functions: 17 21 81.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             :  * src/backend/regex/regc_color.c
      32             :  *
      33             :  *
      34             :  * Note that there are some incestuous relationships between this code and
      35             :  * NFA arc maintenance, which perhaps ought to be cleaned up sometime.
      36             :  */
      37             : 
      38             : 
      39             : 
      40             : #define CISERR()    VISERR(cm->v)
      41             : #define CERR(e)     VERR(cm->v, (e))
      42             : 
      43             : 
      44             : 
      45             : /*
      46             :  * initcm - set up new colormap
      47             :  */
      48             : static void
      49         253 : initcm(struct vars *v,
      50             :        struct colormap *cm)
      51             : {
      52             :     struct colordesc *cd;
      53             : 
      54         253 :     cm->magic = CMMAGIC;
      55         253 :     cm->v = v;
      56             : 
      57         253 :     cm->ncds = NINLINECDS;
      58         253 :     cm->cd = cm->cdspace;
      59         253 :     cm->max = 0;
      60         253 :     cm->free = 0;
      61             : 
      62         253 :     cd = cm->cd;             /* cm->cd[WHITE] */
      63         253 :     cd->nschrs = MAX_SIMPLE_CHR - CHR_MIN + 1;
      64         253 :     cd->nuchrs = 1;
      65         253 :     cd->sub = NOSUB;
      66         253 :     cd->arcs = NULL;
      67         253 :     cd->firstchr = CHR_MIN;
      68         253 :     cd->flags = 0;
      69             : 
      70         253 :     cm->locolormap = (color *)
      71         253 :         MALLOC((MAX_SIMPLE_CHR - CHR_MIN + 1) * sizeof(color));
      72         253 :     if (cm->locolormap == NULL)
      73             :     {
      74           0 :         CERR(REG_ESPACE);
      75           0 :         cm->cmranges = NULL; /* prevent failure during freecm */
      76           0 :         cm->hicolormap = NULL;
      77           0 :         return;
      78             :     }
      79             :     /* this memset relies on WHITE being zero: */
      80         253 :     memset(cm->locolormap, WHITE,
      81             :            (MAX_SIMPLE_CHR - CHR_MIN + 1) * sizeof(color));
      82             : 
      83         253 :     memset(cm->classbits, 0, sizeof(cm->classbits));
      84         253 :     cm->numcmranges = 0;
      85         253 :     cm->cmranges = NULL;
      86         253 :     cm->maxarrayrows = 4;        /* arbitrary initial allocation */
      87         253 :     cm->hiarrayrows = 1;     /* but we have only one row/col initially */
      88         253 :     cm->hiarraycols = 1;
      89         253 :     cm->hicolormap = (color *) MALLOC(cm->maxarrayrows * sizeof(color));
      90         253 :     if (cm->hicolormap == NULL)
      91             :     {
      92           0 :         CERR(REG_ESPACE);
      93           0 :         return;
      94             :     }
      95             :     /* initialize the "all other characters" row to WHITE */
      96         253 :     cm->hicolormap[0] = WHITE;
      97             : }
      98             : 
      99             : /*
     100             :  * freecm - free dynamically-allocated things in a colormap
     101             :  */
     102             : static void
     103          32 : freecm(struct colormap *cm)
     104             : {
     105          32 :     cm->magic = 0;
     106          32 :     if (cm->cd != cm->cdspace)
     107           0 :         FREE(cm->cd);
     108          32 :     if (cm->locolormap != NULL)
     109          32 :         FREE(cm->locolormap);
     110          32 :     if (cm->cmranges != NULL)
     111           0 :         FREE(cm->cmranges);
     112          32 :     if (cm->hicolormap != NULL)
     113          32 :         FREE(cm->hicolormap);
     114          32 : }
     115             : 
     116             : /*
     117             :  * pg_reg_getcolor - slow case of GETCOLOR()
     118             :  */
     119             : color
     120           0 : pg_reg_getcolor(struct colormap *cm, chr c)
     121             : {
     122             :     int         rownum,
     123             :                 colnum,
     124             :                 low,
     125             :                 high;
     126             : 
     127             :     /* Should not be used for chrs in the locolormap */
     128           0 :     assert(c > MAX_SIMPLE_CHR);
     129             : 
     130             :     /*
     131             :      * Find which row it's in.  The colormapranges are in order, so we can use
     132             :      * binary search.
     133             :      */
     134           0 :     rownum = 0;                 /* if no match, use array row zero */
     135           0 :     low = 0;
     136           0 :     high = cm->numcmranges;
     137           0 :     while (low < high)
     138             :     {
     139           0 :         int         middle = low + (high - low) / 2;
     140           0 :         const colormaprange *cmr = &cm->cmranges[middle];
     141             : 
     142           0 :         if (c < cmr->cmin)
     143           0 :             high = middle;
     144           0 :         else if (c > cmr->cmax)
     145           0 :             low = middle + 1;
     146             :         else
     147             :         {
     148           0 :             rownum = cmr->rownum;    /* found a match */
     149           0 :             break;
     150             :         }
     151             :     }
     152             : 
     153             :     /*
     154             :      * Find which column it's in --- this is all locale-dependent.
     155             :      */
     156           0 :     if (cm->hiarraycols > 1)
     157             :     {
     158           0 :         colnum = cclass_column_index(cm, c);
     159           0 :         return cm->hicolormap[rownum * cm->hiarraycols + colnum];
     160             :     }
     161             :     else
     162             :     {
     163             :         /* fast path if no relevant cclasses */
     164           0 :         return cm->hicolormap[rownum];
     165             :     }
     166             : }
     167             : 
     168             : /*
     169             :  * maxcolor - report largest color number in use
     170             :  */
     171             : static color
     172        1778 : maxcolor(struct colormap *cm)
     173             : {
     174        1778 :     if (CISERR())
     175           0 :         return COLORLESS;
     176             : 
     177        1778 :     return (color) cm->max;
     178             : }
     179             : 
     180             : /*
     181             :  * newcolor - find a new color (must be assigned at once)
     182             :  * Beware:  may relocate the colordescs.
     183             :  */
     184             : static color                    /* COLORLESS for error */
     185        2474 : newcolor(struct colormap *cm)
     186             : {
     187             :     struct colordesc *cd;
     188             :     size_t      n;
     189             : 
     190        2474 :     if (CISERR())
     191           0 :         return COLORLESS;
     192             : 
     193        2474 :     if (cm->free != 0)
     194             :     {
     195           6 :         assert(cm->free > 0);
     196           6 :         assert((size_t) cm->free < cm->ncds);
     197           6 :         cd = &cm->cd[cm->free];
     198           6 :         assert(UNUSEDCOLOR(cd));
     199           6 :         assert(cd->arcs == NULL);
     200           6 :         cm->free = cd->sub;
     201             :     }
     202        2468 :     else if (cm->max < cm->ncds - 1)
     203             :     {
     204        2333 :         cm->max++;
     205        2333 :         cd = &cm->cd[cm->max];
     206             :     }
     207             :     else
     208             :     {
     209             :         /* oops, must allocate more */
     210             :         struct colordesc *newCd;
     211             : 
     212         135 :         if (cm->max == MAX_COLOR)
     213             :         {
     214           0 :             CERR(REG_ECOLORS);
     215           0 :             return COLORLESS;   /* too many colors */
     216             :         }
     217             : 
     218         135 :         n = cm->ncds * 2;
     219         135 :         if (n > MAX_COLOR + 1)
     220           0 :             n = MAX_COLOR + 1;
     221         135 :         if (cm->cd == cm->cdspace)
     222             :         {
     223         135 :             newCd = (struct colordesc *) MALLOC(n * sizeof(struct colordesc));
     224         135 :             if (newCd != NULL)
     225         135 :                 memcpy(VS(newCd), VS(cm->cdspace), cm->ncds *
     226             :                        sizeof(struct colordesc));
     227             :         }
     228             :         else
     229           0 :             newCd = (struct colordesc *)
     230           0 :                 REALLOC(cm->cd, n * sizeof(struct colordesc));
     231         135 :         if (newCd == NULL)
     232             :         {
     233           0 :             CERR(REG_ESPACE);
     234           0 :             return COLORLESS;
     235             :         }
     236         135 :         cm->cd = newCd;
     237         135 :         cm->ncds = n;
     238         135 :         assert(cm->max < cm->ncds - 1);
     239         135 :         cm->max++;
     240         135 :         cd = &cm->cd[cm->max];
     241             :     }
     242             : 
     243        2474 :     cd->nschrs = 0;
     244        2474 :     cd->nuchrs = 0;
     245        2474 :     cd->sub = NOSUB;
     246        2474 :     cd->arcs = NULL;
     247        2474 :     cd->firstchr = CHR_MIN;      /* in case never set otherwise */
     248        2474 :     cd->flags = 0;
     249             : 
     250        2474 :     return (color) (cd - cm->cd);
     251             : }
     252             : 
     253             : /*
     254             :  * freecolor - free a color (must have no arcs or subcolor)
     255             :  */
     256             : static void
     257           9 : freecolor(struct colormap *cm,
     258             :           color co)
     259             : {
     260           9 :     struct colordesc *cd = &cm->cd[co];
     261             :     color       pco,
     262             :                 nco;            /* for freelist scan */
     263             : 
     264           9 :     assert(co >= 0);
     265           9 :     if (co == WHITE)
     266           9 :         return;
     267             : 
     268           9 :     assert(cd->arcs == NULL);
     269           9 :     assert(cd->sub == NOSUB);
     270           9 :     assert(cd->nschrs == 0);
     271           9 :     assert(cd->nuchrs == 0);
     272           9 :     cd->flags = FREECOL;
     273             : 
     274           9 :     if ((size_t) co == cm->max)
     275             :     {
     276           7 :         while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max]))
     277           3 :             cm->max--;
     278           2 :         assert(cm->free >= 0);
     279           5 :         while ((size_t) cm->free > cm->max)
     280           1 :             cm->free = cm->cd[cm->free].sub;
     281           2 :         if (cm->free > 0)
     282             :         {
     283           0 :             assert(cm->free < cm->max);
     284           0 :             pco = cm->free;
     285           0 :             nco = cm->cd[pco].sub;
     286           0 :             while (nco > 0)
     287           0 :                 if ((size_t) nco > cm->max)
     288             :                 {
     289             :                     /* take this one out of freelist */
     290           0 :                     nco = cm->cd[nco].sub;
     291           0 :                     cm->cd[pco].sub = nco;
     292             :                 }
     293             :                 else
     294             :                 {
     295           0 :                     assert(nco < cm->max);
     296           0 :                     pco = nco;
     297           0 :                     nco = cm->cd[pco].sub;
     298             :                 }
     299             :         }
     300             :     }
     301             :     else
     302             :     {
     303           7 :         cd->sub = cm->free;
     304           7 :         cm->free = (color) (cd - cm->cd);
     305             :     }
     306             : }
     307             : 
     308             : /*
     309             :  * pseudocolor - allocate a false color, to be managed by other means
     310             :  */
     311             : static color
     312         992 : pseudocolor(struct colormap *cm)
     313             : {
     314             :     color       co;
     315             :     struct colordesc *cd;
     316             : 
     317         992 :     co = newcolor(cm);
     318         992 :     if (CISERR())
     319           0 :         return COLORLESS;
     320         992 :     cd = &cm->cd[co];
     321         992 :     cd->nschrs = 0;
     322         992 :     cd->nuchrs = 1;              /* pretend it is in the upper map */
     323         992 :     cd->sub = NOSUB;
     324         992 :     cd->arcs = NULL;
     325         992 :     cd->firstchr = CHR_MIN;
     326         992 :     cd->flags = PSEUDO;
     327         992 :     return co;
     328             : }
     329             : 
     330             : /*
     331             :  * subcolor - allocate a new subcolor (if necessary) to this chr
     332             :  *
     333             :  * This works only for chrs that map into the low color map.
     334             :  */
     335             : static color
     336       19869 : subcolor(struct colormap *cm, chr c)
     337             : {
     338             :     color       co;             /* current color of c */
     339             :     color       sco;            /* new subcolor */
     340             : 
     341       19869 :     assert(c <= MAX_SIMPLE_CHR);
     342             : 
     343       19869 :     co = cm->locolormap[c - CHR_MIN];
     344       19869 :     sco = newsub(cm, co);
     345       19869 :     if (CISERR())
     346           0 :         return COLORLESS;
     347       19869 :     assert(sco != COLORLESS);
     348             : 
     349       19869 :     if (co == sco)              /* already in an open subcolor */
     350        3577 :         return co;              /* rest is redundant */
     351       16292 :     cm->cd[co].nschrs--;
     352       16292 :     if (cm->cd[sco].nschrs == 0)
     353        1482 :         cm->cd[sco].firstchr = c;
     354       16292 :     cm->cd[sco].nschrs++;
     355       16292 :     cm->locolormap[c - CHR_MIN] = sco;
     356       16292 :     return sco;
     357             : }
     358             : 
     359             : /*
     360             :  * subcolorhi - allocate a new subcolor (if necessary) to this colormap entry
     361             :  *
     362             :  * This is the same processing as subcolor(), but for entries in the high
     363             :  * colormap, which do not necessarily correspond to exactly one chr code.
     364             :  */
     365             : static color
     366          18 : subcolorhi(struct colormap *cm, color *pco)
     367             : {
     368             :     color       co;             /* current color of entry */
     369             :     color       sco;            /* new subcolor */
     370             : 
     371          18 :     co = *pco;
     372          18 :     sco = newsub(cm, co);
     373          18 :     if (CISERR())
     374           0 :         return COLORLESS;
     375          18 :     assert(sco != COLORLESS);
     376             : 
     377          18 :     if (co == sco)              /* already in an open subcolor */
     378           0 :         return co;              /* rest is redundant */
     379          18 :     cm->cd[co].nuchrs--;
     380          18 :     cm->cd[sco].nuchrs++;
     381          18 :     *pco = sco;
     382          18 :     return sco;
     383             : }
     384             : 
     385             : /*
     386             :  * newsub - allocate a new subcolor (if necessary) for a color
     387             :  */
     388             : static color
     389       19887 : newsub(struct colormap *cm,
     390             :        color co)
     391             : {
     392             :     color       sco;            /* new subcolor */
     393             : 
     394       19887 :     sco = cm->cd[co].sub;
     395       19887 :     if (sco == NOSUB)
     396             :     {                           /* color has no open subcolor */
     397             :         /* optimization: singly-referenced color need not be subcolored */
     398        5059 :         if ((cm->cd[co].nschrs + cm->cd[co].nuchrs) == 1)
     399        3577 :             return co;
     400        1482 :         sco = newcolor(cm);     /* must create subcolor */
     401        1482 :         if (sco == COLORLESS)
     402             :         {
     403           0 :             assert(CISERR());
     404           0 :             return COLORLESS;
     405             :         }
     406        1482 :         cm->cd[co].sub = sco;
     407        1482 :         cm->cd[sco].sub = sco;   /* open subcolor points to self */
     408             :     }
     409       16310 :     assert(sco != NOSUB);
     410             : 
     411       16310 :     return sco;
     412             : }
     413             : 
     414             : /*
     415             :  * newhicolorrow - get a new row in the hicolormap, cloning it from oldrow
     416             :  *
     417             :  * Returns array index of new row.  Note the array might move.
     418             :  */
     419             : static int
     420           0 : newhicolorrow(struct colormap *cm,
     421             :               int oldrow)
     422             : {
     423           0 :     int         newrow = cm->hiarrayrows;
     424             :     color      *newrowptr;
     425             :     int         i;
     426             : 
     427             :     /* Assign a fresh array row index, enlarging storage if needed */
     428           0 :     if (newrow >= cm->maxarrayrows)
     429             :     {
     430             :         color      *newarray;
     431             : 
     432           0 :         if (cm->maxarrayrows >= INT_MAX / (cm->hiarraycols * 2))
     433             :         {
     434           0 :             CERR(REG_ESPACE);
     435           0 :             return 0;
     436             :         }
     437           0 :         newarray = (color *) REALLOC(cm->hicolormap,
     438             :                                      cm->maxarrayrows * 2 *
     439             :                                      cm->hiarraycols * sizeof(color));
     440           0 :         if (newarray == NULL)
     441             :         {
     442           0 :             CERR(REG_ESPACE);
     443           0 :             return 0;
     444             :         }
     445           0 :         cm->hicolormap = newarray;
     446           0 :         cm->maxarrayrows *= 2;
     447             :     }
     448           0 :     cm->hiarrayrows++;
     449             : 
     450             :     /* Copy old row data */
     451           0 :     newrowptr = &cm->hicolormap[newrow * cm->hiarraycols];
     452           0 :     memcpy(newrowptr,
     453           0 :            &cm->hicolormap[oldrow * cm->hiarraycols],
     454           0 :            cm->hiarraycols * sizeof(color));
     455             : 
     456             :     /* Increase color reference counts to reflect new colormap entries */
     457           0 :     for (i = 0; i < cm->hiarraycols; i++)
     458           0 :         cm->cd[newrowptr[i]].nuchrs++;
     459             : 
     460           0 :     return newrow;
     461             : }
     462             : 
     463             : /*
     464             :  * newhicolorcols - create a new set of columns in the high colormap
     465             :  *
     466             :  * Essentially, extends the 2-D array to the right with a copy of itself.
     467             :  */
     468             : static void
     469          15 : newhicolorcols(struct colormap *cm)
     470             : {
     471             :     color      *newarray;
     472             :     int         r,
     473             :                 c;
     474             : 
     475          15 :     if (cm->hiarraycols >= INT_MAX / (cm->maxarrayrows * 2))
     476             :     {
     477           0 :         CERR(REG_ESPACE);
     478           0 :         return;
     479             :     }
     480          15 :     newarray = (color *) REALLOC(cm->hicolormap,
     481             :                                  cm->maxarrayrows *
     482             :                                  cm->hiarraycols * 2 * sizeof(color));
     483          15 :     if (newarray == NULL)
     484             :     {
     485           0 :         CERR(REG_ESPACE);
     486           0 :         return;
     487             :     }
     488          15 :     cm->hicolormap = newarray;
     489             : 
     490             :     /* Duplicate existing columns to the right, and increase ref counts */
     491             :     /* Must work backwards in the array because we realloc'd in place */
     492          30 :     for (r = cm->hiarrayrows - 1; r >= 0; r--)
     493             :     {
     494          15 :         color      *oldrowptr = &newarray[r * cm->hiarraycols];
     495          15 :         color      *newrowptr = &newarray[r * cm->hiarraycols * 2];
     496          15 :         color      *newrowptr2 = newrowptr + cm->hiarraycols;
     497             : 
     498          30 :         for (c = 0; c < cm->hiarraycols; c++)
     499             :         {
     500          15 :             color       co = oldrowptr[c];
     501             : 
     502          15 :             newrowptr[c] = newrowptr2[c] = co;
     503          15 :             cm->cd[co].nuchrs++;
     504             :         }
     505             :     }
     506             : 
     507          15 :     cm->hiarraycols *= 2;
     508             : }
     509             : 
     510             : /*
     511             :  * subcolorcvec - allocate new subcolors to cvec members, fill in arcs
     512             :  *
     513             :  * For each chr "c" represented by the cvec, do the equivalent of
     514             :  * newarc(v->nfa, PLAIN, subcolor(v->cm, c), lp, rp);
     515             :  *
     516             :  * Note that in typical cases, many of the subcolors are the same.
     517             :  * While newarc() would discard duplicate arc requests, we can save
     518             :  * some cycles by not calling it repetitively to begin with.  This is
     519             :  * mechanized with the "lastsubcolor" state variable.
     520             :  */
     521             : static void
     522          48 : subcolorcvec(struct vars *v,
     523             :              struct cvec *cv,
     524             :              struct state *lp,
     525             :              struct state *rp)
     526             : {
     527          48 :     struct colormap *cm = v->cm;
     528          48 :     color       lastsubcolor = COLORLESS;
     529             :     chr         ch,
     530             :                 from,
     531             :                 to;
     532             :     const chr  *p;
     533             :     int         i;
     534             : 
     535             :     /* ordinary characters */
     536         212 :     for (p = cv->chrs, i = cv->nchrs; i > 0; p++, i--)
     537             :     {
     538         164 :         ch = *p;
     539         164 :         subcoloronechr(v, ch, lp, rp, &lastsubcolor);
     540         164 :         NOERR();
     541             :     }
     542             : 
     543             :     /* and the ranges */
     544         380 :     for (p = cv->ranges, i = cv->nranges; i > 0; p += 2, i--)
     545             :     {
     546         332 :         from = *p;
     547         332 :         to = *(p + 1);
     548         332 :         if (from <= MAX_SIMPLE_CHR)
     549             :         {
     550             :             /* deal with simple chars one at a time */
     551         332 :             chr         lim = (to <= MAX_SIMPLE_CHR) ? to : MAX_SIMPLE_CHR;
     552             : 
     553       15381 :             while (from <= lim)
     554             :             {
     555       14717 :                 color       sco = subcolor(cm, from);
     556             : 
     557       14717 :                 NOERR();
     558       14717 :                 if (sco != lastsubcolor)
     559             :                 {
     560          99 :                     newarc(v->nfa, PLAIN, sco, lp, rp);
     561          99 :                     NOERR();
     562          99 :                     lastsubcolor = sco;
     563             :                 }
     564       14717 :                 from++;
     565             :             }
     566             :         }
     567             :         /* deal with any part of the range that's above MAX_SIMPLE_CHR */
     568         332 :         if (from < to)
     569           0 :             subcoloronerange(v, from, to, lp, rp, &lastsubcolor);
     570         332 :         else if (from == to)
     571           0 :             subcoloronechr(v, from, lp, rp, &lastsubcolor);
     572         332 :         NOERR();
     573             :     }
     574             : 
     575             :     /* and deal with cclass if any */
     576          48 :     if (cv->cclasscode >= 0)
     577             :     {
     578             :         int         classbit;
     579             :         color      *pco;
     580             :         int         r,
     581             :                     c;
     582             : 
     583             :         /* Enlarge array if we don't have a column bit assignment for cclass */
     584          18 :         if (cm->classbits[cv->cclasscode] == 0)
     585             :         {
     586          15 :             cm->classbits[cv->cclasscode] = cm->hiarraycols;
     587          15 :             newhicolorcols(cm);
     588          15 :             NOERR();
     589             :         }
     590             :         /* Apply subcolorhi() and make arc for each entry in relevant cols */
     591          18 :         classbit = cm->classbits[cv->cclasscode];
     592          18 :         pco = cm->hicolormap;
     593          36 :         for (r = 0; r < cm->hiarrayrows; r++)
     594             :         {
     595          54 :             for (c = 0; c < cm->hiarraycols; c++)
     596             :             {
     597          36 :                 if (c & classbit)
     598             :                 {
     599          18 :                     color       sco = subcolorhi(cm, pco);
     600             : 
     601          18 :                     NOERR();
     602             :                     /* add the arc if needed */
     603          18 :                     if (sco != lastsubcolor)
     604             :                     {
     605           0 :                         newarc(v->nfa, PLAIN, sco, lp, rp);
     606           0 :                         NOERR();
     607           0 :                         lastsubcolor = sco;
     608             :                     }
     609             :                 }
     610          36 :                 pco++;
     611             :             }
     612             :         }
     613             :     }
     614             : }
     615             : 
     616             : /*
     617             :  * subcoloronechr - do subcolorcvec's work for a singleton chr
     618             :  *
     619             :  * We could just let subcoloronerange do this, but it's a bit more efficient
     620             :  * if we exploit the single-chr case.  Also, callers find it useful for this
     621             :  * to be able to handle both low and high chr codes.
     622             :  */
     623             : static void
     624        5147 : subcoloronechr(struct vars *v,
     625             :                chr ch,
     626             :                struct state *lp,
     627             :                struct state *rp,
     628             :                color *lastsubcolor)
     629             : {
     630        5147 :     struct colormap *cm = v->cm;
     631             :     colormaprange *newranges;
     632             :     int         numnewranges;
     633             :     colormaprange *oldrange;
     634             :     int         oldrangen;
     635             :     int         newrow;
     636             : 
     637             :     /* Easy case for low chr codes */
     638        5147 :     if (ch <= MAX_SIMPLE_CHR)
     639             :     {
     640        5147 :         color       sco = subcolor(cm, ch);
     641             : 
     642        5147 :         NOERR();
     643        5147 :         if (sco != *lastsubcolor)
     644             :         {
     645        5012 :             newarc(v->nfa, PLAIN, sco, lp, rp);
     646        5012 :             *lastsubcolor = sco;
     647             :         }
     648        5147 :         return;
     649             :     }
     650             : 
     651             :     /*
     652             :      * Potentially, we could need two more colormapranges than we have now, if
     653             :      * the given chr is in the middle of some existing range.
     654             :      */
     655           0 :     newranges = (colormaprange *)
     656           0 :         MALLOC((cm->numcmranges + 2) * sizeof(colormaprange));
     657           0 :     if (newranges == NULL)
     658             :     {
     659           0 :         CERR(REG_ESPACE);
     660           0 :         return;
     661             :     }
     662           0 :     numnewranges = 0;
     663             : 
     664             :     /* Ranges before target are unchanged */
     665           0 :     for (oldrange = cm->cmranges, oldrangen = 0;
     666           0 :          oldrangen < cm->numcmranges;
     667           0 :          oldrange++, oldrangen++)
     668             :     {
     669           0 :         if (oldrange->cmax >= ch)
     670           0 :             break;
     671           0 :         newranges[numnewranges++] = *oldrange;
     672             :     }
     673             : 
     674             :     /* Match target chr against current range */
     675           0 :     if (oldrangen >= cm->numcmranges || oldrange->cmin > ch)
     676             :     {
     677             :         /* chr does not belong to any existing range, make a new one */
     678           0 :         newranges[numnewranges].cmin = ch;
     679           0 :         newranges[numnewranges].cmax = ch;
     680             :         /* row state should be cloned from the "all others" row */
     681           0 :         newranges[numnewranges].rownum = newrow = newhicolorrow(cm, 0);
     682           0 :         numnewranges++;
     683             :     }
     684           0 :     else if (oldrange->cmin == oldrange->cmax)
     685             :     {
     686             :         /* we have an existing singleton range matching the chr */
     687           0 :         newranges[numnewranges++] = *oldrange;
     688           0 :         newrow = oldrange->rownum;
     689             :         /* we've now fully processed this old range */
     690           0 :         oldrange++, oldrangen++;
     691             :     }
     692             :     else
     693             :     {
     694             :         /* chr is a subset of this existing range, must split it */
     695           0 :         if (ch > oldrange->cmin)
     696             :         {
     697             :             /* emit portion of old range before chr */
     698           0 :             newranges[numnewranges].cmin = oldrange->cmin;
     699           0 :             newranges[numnewranges].cmax = ch - 1;
     700           0 :             newranges[numnewranges].rownum = oldrange->rownum;
     701           0 :             numnewranges++;
     702             :         }
     703             :         /* emit chr as singleton range, initially cloning from range */
     704           0 :         newranges[numnewranges].cmin = ch;
     705           0 :         newranges[numnewranges].cmax = ch;
     706           0 :         newranges[numnewranges].rownum = newrow =
     707           0 :             newhicolorrow(cm, oldrange->rownum);
     708           0 :         numnewranges++;
     709           0 :         if (ch < oldrange->cmax)
     710             :         {
     711             :             /* emit portion of old range after chr */
     712           0 :             newranges[numnewranges].cmin = ch + 1;
     713           0 :             newranges[numnewranges].cmax = oldrange->cmax;
     714             :             /* must clone the row if we are making two new ranges from old */
     715           0 :             newranges[numnewranges].rownum =
     716           0 :                 (ch > oldrange->cmin) ? newhicolorrow(cm, oldrange->rownum) :
     717             :                 oldrange->rownum;
     718           0 :             numnewranges++;
     719             :         }
     720             :         /* we've now fully processed this old range */
     721           0 :         oldrange++, oldrangen++;
     722             :     }
     723             : 
     724             :     /* Update colors in newrow and create arcs as needed */
     725           0 :     subcoloronerow(v, newrow, lp, rp, lastsubcolor);
     726             : 
     727             :     /* Ranges after target are unchanged */
     728           0 :     for (; oldrangen < cm->numcmranges; oldrange++, oldrangen++)
     729             :     {
     730           0 :         newranges[numnewranges++] = *oldrange;
     731             :     }
     732             : 
     733             :     /* Assert our original space estimate was adequate */
     734           0 :     assert(numnewranges <= (cm->numcmranges + 2));
     735             : 
     736             :     /* And finally, store back the updated list of ranges */
     737           0 :     if (cm->cmranges != NULL)
     738           0 :         FREE(cm->cmranges);
     739           0 :     cm->cmranges = newranges;
     740           0 :     cm->numcmranges = numnewranges;
     741             : }
     742             : 
     743             : /*
     744             :  * subcoloronerange - do subcolorcvec's work for a high range
     745             :  */
     746             : static void
     747           0 : subcoloronerange(struct vars *v,
     748             :                  chr from,
     749             :                  chr to,
     750             :                  struct state *lp,
     751             :                  struct state *rp,
     752             :                  color *lastsubcolor)
     753             : {
     754           0 :     struct colormap *cm = v->cm;
     755             :     colormaprange *newranges;
     756             :     int         numnewranges;
     757             :     colormaprange *oldrange;
     758             :     int         oldrangen;
     759             :     int         newrow;
     760             : 
     761             :     /* Caller should take care of non-high-range cases */
     762           0 :     assert(from > MAX_SIMPLE_CHR);
     763           0 :     assert(from < to);
     764             : 
     765             :     /*
     766             :      * Potentially, if we have N non-adjacent ranges, we could need as many as
     767             :      * 2N+1 result ranges (consider case where new range spans 'em all).
     768             :      */
     769           0 :     newranges = (colormaprange *)
     770           0 :         MALLOC((cm->numcmranges * 2 + 1) * sizeof(colormaprange));
     771           0 :     if (newranges == NULL)
     772             :     {
     773           0 :         CERR(REG_ESPACE);
     774           0 :         return;
     775             :     }
     776           0 :     numnewranges = 0;
     777             : 
     778             :     /* Ranges before target are unchanged */
     779           0 :     for (oldrange = cm->cmranges, oldrangen = 0;
     780           0 :          oldrangen < cm->numcmranges;
     781           0 :          oldrange++, oldrangen++)
     782             :     {
     783           0 :         if (oldrange->cmax >= from)
     784           0 :             break;
     785           0 :         newranges[numnewranges++] = *oldrange;
     786             :     }
     787             : 
     788             :     /*
     789             :      * Deal with ranges that (partially) overlap the target.  As we process
     790             :      * each such range, increase "from" to remove the dealt-with characters
     791             :      * from the target range.
     792             :      */
     793           0 :     while (oldrangen < cm->numcmranges && oldrange->cmin <= to)
     794             :     {
     795           0 :         if (from < oldrange->cmin)
     796             :         {
     797             :             /* Handle portion of new range that corresponds to no old range */
     798           0 :             newranges[numnewranges].cmin = from;
     799           0 :             newranges[numnewranges].cmax = oldrange->cmin - 1;
     800             :             /* row state should be cloned from the "all others" row */
     801           0 :             newranges[numnewranges].rownum = newrow = newhicolorrow(cm, 0);
     802           0 :             numnewranges++;
     803             :             /* Update colors in newrow and create arcs as needed */
     804           0 :             subcoloronerow(v, newrow, lp, rp, lastsubcolor);
     805             :             /* We've now fully processed the part of new range before old */
     806           0 :             from = oldrange->cmin;
     807             :         }
     808             : 
     809           0 :         if (from <= oldrange->cmin && to >= oldrange->cmax)
     810             :         {
     811             :             /* old range is fully contained in new, process it in-place */
     812           0 :             newranges[numnewranges++] = *oldrange;
     813           0 :             newrow = oldrange->rownum;
     814           0 :             from = oldrange->cmax + 1;
     815             :         }
     816             :         else
     817             :         {
     818             :             /* some part of old range does not overlap new range */
     819           0 :             if (from > oldrange->cmin)
     820             :             {
     821             :                 /* emit portion of old range before new range */
     822           0 :                 newranges[numnewranges].cmin = oldrange->cmin;
     823           0 :                 newranges[numnewranges].cmax = from - 1;
     824           0 :                 newranges[numnewranges].rownum = oldrange->rownum;
     825           0 :                 numnewranges++;
     826             :             }
     827             :             /* emit common subrange, initially cloning from old range */
     828           0 :             newranges[numnewranges].cmin = from;
     829           0 :             newranges[numnewranges].cmax =
     830           0 :                 (to < oldrange->cmax) ? to : oldrange->cmax;
     831           0 :             newranges[numnewranges].rownum = newrow =
     832           0 :                 newhicolorrow(cm, oldrange->rownum);
     833           0 :             numnewranges++;
     834           0 :             if (to < oldrange->cmax)
     835             :             {
     836             :                 /* emit portion of old range after new range */
     837           0 :                 newranges[numnewranges].cmin = to + 1;
     838           0 :                 newranges[numnewranges].cmax = oldrange->cmax;
     839             :                 /* must clone the row if we are making two new ranges from old */
     840           0 :                 newranges[numnewranges].rownum =
     841           0 :                     (from > oldrange->cmin) ? newhicolorrow(cm, oldrange->rownum) :
     842             :                     oldrange->rownum;
     843           0 :                 numnewranges++;
     844             :             }
     845           0 :             from = oldrange->cmax + 1;
     846             :         }
     847             :         /* Update colors in newrow and create arcs as needed */
     848           0 :         subcoloronerow(v, newrow, lp, rp, lastsubcolor);
     849             :         /* we've now fully processed this old range */
     850           0 :         oldrange++, oldrangen++;
     851             :     }
     852             : 
     853           0 :     if (from <= to)
     854             :     {
     855             :         /* Handle portion of new range that corresponds to no old range */
     856           0 :         newranges[numnewranges].cmin = from;
     857           0 :         newranges[numnewranges].cmax = to;
     858             :         /* row state should be cloned from the "all others" row */
     859           0 :         newranges[numnewranges].rownum = newrow = newhicolorrow(cm, 0);
     860           0 :         numnewranges++;
     861             :         /* Update colors in newrow and create arcs as needed */
     862           0 :         subcoloronerow(v, newrow, lp, rp, lastsubcolor);
     863             :     }
     864             : 
     865             :     /* Ranges after target are unchanged */
     866           0 :     for (; oldrangen < cm->numcmranges; oldrange++, oldrangen++)
     867             :     {
     868           0 :         newranges[numnewranges++] = *oldrange;
     869             :     }
     870             : 
     871             :     /* Assert our original space estimate was adequate */
     872           0 :     assert(numnewranges <= (cm->numcmranges * 2 + 1));
     873             : 
     874             :     /* And finally, store back the updated list of ranges */
     875           0 :     if (cm->cmranges != NULL)
     876           0 :         FREE(cm->cmranges);
     877           0 :     cm->cmranges = newranges;
     878           0 :     cm->numcmranges = numnewranges;
     879             : }
     880             : 
     881             : /*
     882             :  * subcoloronerow - do subcolorcvec's work for one new row in the high colormap
     883             :  */
     884             : static void
     885           0 : subcoloronerow(struct vars *v,
     886             :                int rownum,
     887             :                struct state *lp,
     888             :                struct state *rp,
     889             :                color *lastsubcolor)
     890             : {
     891           0 :     struct colormap *cm = v->cm;
     892             :     color      *pco;
     893             :     int         i;
     894             : 
     895             :     /* Apply subcolorhi() and make arc for each entry in row */
     896           0 :     pco = &cm->hicolormap[rownum * cm->hiarraycols];
     897           0 :     for (i = 0; i < cm->hiarraycols; pco++, i++)
     898             :     {
     899           0 :         color       sco = subcolorhi(cm, pco);
     900             : 
     901           0 :         NOERR();
     902             :         /* make the arc if needed */
     903           0 :         if (sco != *lastsubcolor)
     904             :         {
     905           0 :             newarc(v->nfa, PLAIN, sco, lp, rp);
     906           0 :             NOERR();
     907           0 :             *lastsubcolor = sco;
     908             :         }
     909             :     }
     910             : }
     911             : 
     912             : /*
     913             :  * okcolors - promote subcolors to full colors
     914             :  */
     915             : static void
     916        5003 : okcolors(struct nfa *nfa,
     917             :          struct colormap *cm)
     918             : {
     919             :     struct colordesc *cd;
     920        5003 :     struct colordesc *end = CDEND(cm);
     921             :     struct colordesc *scd;
     922             :     struct arc *a;
     923             :     color       co;
     924             :     color       sco;
     925             : 
     926       30074 :     for (cd = cm->cd, co = 0; cd < end; cd++, co++)
     927             :     {
     928       25071 :         sco = cd->sub;
     929       25071 :         if (UNUSEDCOLOR(cd) || sco == NOSUB)
     930             :         {
     931             :             /* has no subcolor, no further action */
     932             :         }
     933        1486 :         else if (sco == co)
     934             :         {
     935             :             /* is subcolor, let parent deal with it */
     936             :         }
     937        1482 :         else if (cd->nschrs == 0 && cd->nuchrs == 0)
     938             :         {
     939             :             /* parent empty, its arcs change color to subcolor */
     940           9 :             cd->sub = NOSUB;
     941           9 :             scd = &cm->cd[sco];
     942           9 :             assert(scd->nschrs > 0 || scd->nuchrs > 0);
     943           9 :             assert(scd->sub == sco);
     944           9 :             scd->sub = NOSUB;
     945          56 :             while ((a = cd->arcs) != NULL)
     946             :             {
     947          38 :                 assert(a->co == co);
     948          38 :                 uncolorchain(cm, a);
     949          38 :                 a->co = sco;
     950          38 :                 colorchain(cm, a);
     951             :             }
     952           9 :             freecolor(cm, co);
     953             :         }
     954             :         else
     955             :         {
     956             :             /* parent's arcs must gain parallel subcolor arcs */
     957        1473 :             cd->sub = NOSUB;
     958        1473 :             scd = &cm->cd[sco];
     959        1473 :             assert(scd->nschrs > 0 || scd->nuchrs > 0);
     960        1473 :             assert(scd->sub == sco);
     961        1473 :             scd->sub = NOSUB;
     962        4468 :             for (a = cd->arcs; a != NULL; a = a->colorchain)
     963             :             {
     964        2995 :                 assert(a->co == co);
     965        2995 :                 newarc(nfa, a->type, sco, a->from, a->to);
     966             :             }
     967             :         }
     968             :     }
     969        5003 : }
     970             : 
     971             : /*
     972             :  * colorchain - add this arc to the color chain of its color
     973             :  */
     974             : static void
     975       31367 : colorchain(struct colormap *cm,
     976             :            struct arc *a)
     977             : {
     978       31367 :     struct colordesc *cd = &cm->cd[a->co];
     979             : 
     980       31367 :     if (cd->arcs != NULL)
     981       28960 :         cd->arcs->colorchainRev = a;
     982       31367 :     a->colorchain = cd->arcs;
     983       31367 :     a->colorchainRev = NULL;
     984       31367 :     cd->arcs = a;
     985       31367 : }
     986             : 
     987             : /*
     988             :  * uncolorchain - delete this arc from the color chain of its color
     989             :  */
     990             : static void
     991       22555 : uncolorchain(struct colormap *cm,
     992             :              struct arc *a)
     993             : {
     994       22555 :     struct colordesc *cd = &cm->cd[a->co];
     995       22555 :     struct arc *aa = a->colorchainRev;
     996             : 
     997       22555 :     if (aa == NULL)
     998             :     {
     999        5612 :         assert(cd->arcs == a);
    1000        5612 :         cd->arcs = a->colorchain;
    1001             :     }
    1002             :     else
    1003             :     {
    1004       16943 :         assert(aa->colorchain == a);
    1005       16943 :         aa->colorchain = a->colorchain;
    1006             :     }
    1007       22555 :     if (a->colorchain != NULL)
    1008       19325 :         a->colorchain->colorchainRev = aa;
    1009       22555 :     a->colorchain = NULL;        /* paranoia */
    1010       22555 :     a->colorchainRev = NULL;
    1011       22555 : }
    1012             : 
    1013             : /*
    1014             :  * rainbow - add arcs of all full colors (but one) between specified states
    1015             :  */
    1016             : static void
    1017        3680 : rainbow(struct nfa *nfa,
    1018             :         struct colormap *cm,
    1019             :         int type,
    1020             :         color but,              /* COLORLESS if no exceptions */
    1021             :         struct state *from,
    1022             :         struct state *to)
    1023             : {
    1024             :     struct colordesc *cd;
    1025        3680 :     struct colordesc *end = CDEND(cm);
    1026             :     color       co;
    1027             : 
    1028       38456 :     for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
    1029       69549 :         if (!UNUSEDCOLOR(cd) && cd->sub != co && co != but &&
    1030       34773 :             !(cd->flags & PSEUDO))
    1031       22185 :             newarc(nfa, type, co, from, to);
    1032        3680 : }
    1033             : 
    1034             : /*
    1035             :  * colorcomplement - add arcs of complementary colors
    1036             :  *
    1037             :  * The calling sequence ought to be reconciled with cloneouts().
    1038             :  */
    1039             : static void
    1040          20 : colorcomplement(struct nfa *nfa,
    1041             :                 struct colormap *cm,
    1042             :                 int type,
    1043             :                 struct state *of,   /* complements of this guy's PLAIN outarcs */
    1044             :                 struct state *from,
    1045             :                 struct state *to)
    1046             : {
    1047             :     struct colordesc *cd;
    1048          20 :     struct colordesc *end = CDEND(cm);
    1049             :     color       co;
    1050             : 
    1051          20 :     assert(of != from);
    1052          91 :     for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
    1053          71 :         if (!UNUSEDCOLOR(cd) && !(cd->flags & PSEUDO))
    1054          71 :             if (findarc(of, PLAIN, co) == NULL)
    1055          32 :                 newarc(nfa, type, co, from, to);
    1056          20 : }
    1057             : 
    1058             : 
    1059             : #ifdef REG_DEBUG
    1060             : 
    1061             : /*
    1062             :  * dumpcolors - debugging output
    1063             :  */
    1064             : static void
    1065             : dumpcolors(struct colormap *cm,
    1066             :            FILE *f)
    1067             : {
    1068             :     struct colordesc *cd;
    1069             :     struct colordesc *end;
    1070             :     color       co;
    1071             :     chr         c;
    1072             : 
    1073             :     fprintf(f, "max %ld\n", (long) cm->max);
    1074             :     end = CDEND(cm);
    1075             :     for (cd = cm->cd + 1, co = 1; cd < end; cd++, co++) /* skip 0 */
    1076             :     {
    1077             :         if (!UNUSEDCOLOR(cd))
    1078             :         {
    1079             :             assert(cd->nschrs > 0 || cd->nuchrs > 0);
    1080             :             if (cd->flags & PSEUDO)
    1081             :                 fprintf(f, "#%2ld(ps): ", (long) co);
    1082             :             else
    1083             :                 fprintf(f, "#%2ld(%2d): ", (long) co, cd->nschrs + cd->nuchrs);
    1084             : 
    1085             :             /*
    1086             :              * Unfortunately, it's hard to do this next bit more efficiently.
    1087             :              */
    1088             :             for (c = CHR_MIN; c <= MAX_SIMPLE_CHR; c++)
    1089             :                 if (GETCOLOR(cm, c) == co)
    1090             :                     dumpchr(c, f);
    1091             :             fprintf(f, "\n");
    1092             :         }
    1093             :     }
    1094             :     /* dump the high colormap if it contains anything interesting */
    1095             :     if (cm->hiarrayrows > 1 || cm->hiarraycols > 1)
    1096             :     {
    1097             :         int         r,
    1098             :                     c;
    1099             :         const color *rowptr;
    1100             : 
    1101             :         fprintf(f, "other:\t");
    1102             :         for (c = 0; c < cm->hiarraycols; c++)
    1103             :         {
    1104             :             fprintf(f, "\t%ld", (long) cm->hicolormap[c]);
    1105             :         }
    1106             :         fprintf(f, "\n");
    1107             :         for (r = 0; r < cm->numcmranges; r++)
    1108             :         {
    1109             :             dumpchr(cm->cmranges[r].cmin, f);
    1110             :             fprintf(f, "..");
    1111             :             dumpchr(cm->cmranges[r].cmax, f);
    1112             :             fprintf(f, ":");
    1113             :             rowptr = &cm->hicolormap[cm->cmranges[r].rownum * cm->hiarraycols];
    1114             :             for (c = 0; c < cm->hiarraycols; c++)
    1115             :             {
    1116             :                 fprintf(f, "\t%ld", (long) rowptr[c]);
    1117             :             }
    1118             :             fprintf(f, "\n");
    1119             :         }
    1120             :     }
    1121             : }
    1122             : 
    1123             : /*
    1124             :  * dumpchr - print a chr
    1125             :  *
    1126             :  * Kind of char-centric but works well enough for debug use.
    1127             :  */
    1128             : static void
    1129             : dumpchr(chr c,
    1130             :         FILE *f)
    1131             : {
    1132             :     if (c == '\\')
    1133             :         fprintf(f, "\\\\");
    1134             :     else if (c > ' ' && c <= '~')
    1135             :         putc((char) c, f);
    1136             :     else
    1137             :         fprintf(f, "\\u%04lx", (long) c);
    1138             : }
    1139             : 
    1140             : #endif                          /* REG_DEBUG */

Generated by: LCOV version 1.11