LCOV - code coverage report
Current view: top level - src/backend/regex - regc_color.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 63.3 % 583 369
Test Date: 2026-01-26 10:56:24 Functions: 85.7 % 21 18
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 45.9 % 381 175

             Branch data     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                 :         812 : initcm(struct vars *v,
      50                 :             :            struct colormap *cm)
      51                 :             : {
      52                 :         812 :         struct colordesc *cd;
      53                 :             : 
      54                 :         812 :         cm->magic = CMMAGIC;
      55                 :         812 :         cm->v = v;
      56                 :             : 
      57                 :         812 :         cm->ncds = NINLINECDS;
      58                 :         812 :         cm->cd = cm->cdspace;
      59                 :         812 :         cm->max = 0;
      60                 :         812 :         cm->free = 0;
      61                 :             : 
      62                 :         812 :         cd = cm->cd;                         /* cm->cd[WHITE] */
      63                 :         812 :         cd->nschrs = MAX_SIMPLE_CHR - CHR_MIN + 1;
      64                 :         812 :         cd->nuchrs = 1;
      65                 :         812 :         cd->sub = NOSUB;
      66                 :         812 :         cd->arcs = NULL;
      67                 :         812 :         cd->firstchr = CHR_MIN;
      68                 :         812 :         cd->flags = 0;
      69                 :             : 
      70                 :         812 :         cm->locolormap = (color *)
      71                 :         812 :                 MALLOC((MAX_SIMPLE_CHR - CHR_MIN + 1) * sizeof(color));
      72         [ +  - ]:         812 :         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                 :         812 :         memset(cm->locolormap, WHITE,
      81                 :             :                    (MAX_SIMPLE_CHR - CHR_MIN + 1) * sizeof(color));
      82                 :             : 
      83                 :         812 :         memset(cm->classbits, 0, sizeof(cm->classbits));
      84                 :         812 :         cm->numcmranges = 0;
      85                 :         812 :         cm->cmranges = NULL;
      86                 :         812 :         cm->maxarrayrows = 4;                /* arbitrary initial allocation */
      87                 :         812 :         cm->hiarrayrows = 1;         /* but we have only one row/col initially */
      88                 :         812 :         cm->hiarraycols = 1;
      89                 :         812 :         cm->hicolormap = (color *) MALLOC(cm->maxarrayrows * sizeof(color));
      90         [ +  - ]:         812 :         if (cm->hicolormap == NULL)
      91                 :             :         {
      92         [ #  # ]:           0 :                 CERR(REG_ESPACE);
      93                 :           0 :                 return;
      94                 :             :         }
      95                 :             :         /* initialize the "all other characters" row to WHITE */
      96                 :         812 :         cm->hicolormap[0] = WHITE;
      97         [ -  + ]:         812 : }
      98                 :             : 
      99                 :             : /*
     100                 :             :  * freecm - free dynamically-allocated things in a colormap
     101                 :             :  */
     102                 :             : static void
     103                 :          27 : freecm(struct colormap *cm)
     104                 :             : {
     105                 :          27 :         cm->magic = 0;
     106         [ +  + ]:          27 :         if (cm->cd != cm->cdspace)
     107                 :          11 :                 FREE(cm->cd);
     108         [ -  + ]:          27 :         if (cm->locolormap != NULL)
     109                 :          27 :                 FREE(cm->locolormap);
     110         [ +  - ]:          27 :         if (cm->cmranges != NULL)
     111                 :           0 :                 FREE(cm->cmranges);
     112         [ -  + ]:          27 :         if (cm->hicolormap != NULL)
     113                 :          27 :                 FREE(cm->hicolormap);
     114                 :          27 : }
     115                 :             : 
     116                 :             : /*
     117                 :             :  * pg_reg_getcolor - slow case of GETCOLOR()
     118                 :             :  */
     119                 :             : color
     120                 :           2 : pg_reg_getcolor(struct colormap *cm, chr c)
     121                 :             : {
     122                 :           2 :         int                     rownum,
     123                 :             :                                 colnum,
     124                 :             :                                 low,
     125                 :             :                                 high;
     126                 :             : 
     127                 :             :         /* Should not be used for chrs in the locolormap */
     128         [ +  - ]:           2 :         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                 :           2 :         rownum = 0;                                     /* if no match, use array row zero */
     135                 :           2 :         low = 0;
     136                 :           2 :         high = cm->numcmranges;
     137         [ +  - ]:           2 :         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      [ #  #  # ]:           0 :         }
     152                 :             : 
     153                 :             :         /*
     154                 :             :          * Find which column it's in --- this is all locale-dependent.
     155                 :             :          */
     156         [ +  - ]:           2 :         if (cm->hiarraycols > 1)
     157                 :             :         {
     158                 :           2 :                 colnum = cclass_column_index(cm, c);
     159                 :           2 :                 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                 :           2 : }
     167                 :             : 
     168                 :             : /*
     169                 :             :  * maxcolor - report largest color number in use
     170                 :             :  */
     171                 :             : static color
     172                 :        1923 : maxcolor(struct colormap *cm)
     173                 :             : {
     174         [ -  + ]:        1923 :         if (CISERR())
     175                 :           0 :                 return COLORLESS;
     176                 :             : 
     177                 :        1923 :         return (color) cm->max;
     178                 :        1923 : }
     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                 :        8729 : newcolor(struct colormap *cm)
     186                 :             : {
     187                 :        8729 :         struct colordesc *cd;
     188                 :        8729 :         size_t          n;
     189                 :             : 
     190         [ -  + ]:        8729 :         if (CISERR())
     191                 :           0 :                 return COLORLESS;
     192                 :             : 
     193         [ +  + ]:        8729 :         if (cm->free != 0)
     194                 :             :         {
     195         [ +  - ]:          23 :                 assert(cm->free > 0);
     196         [ +  - ]:          23 :                 assert((size_t) cm->free < cm->ncds);
     197                 :          23 :                 cd = &cm->cd[cm->free];
     198         [ +  - ]:          23 :                 assert(UNUSEDCOLOR(cd));
     199         [ +  - ]:          23 :                 assert(cd->arcs == NULL);
     200                 :          23 :                 cm->free = cd->sub;
     201                 :          23 :         }
     202         [ +  + ]:        8706 :         else if (cm->max < cm->ncds - 1)
     203                 :             :         {
     204                 :        8219 :                 cm->max++;
     205                 :        8219 :                 cd = &cm->cd[cm->max];
     206                 :        8219 :         }
     207                 :             :         else
     208                 :             :         {
     209                 :             :                 /* oops, must allocate more */
     210                 :         487 :                 struct colordesc *newCd;
     211                 :             : 
     212         [ -  + ]:         487 :                 if (cm->max == MAX_COLOR)
     213                 :             :                 {
     214         [ #  # ]:           0 :                         CERR(REG_ECOLORS);
     215                 :           0 :                         return COLORLESS;       /* too many colors */
     216                 :             :                 }
     217                 :             : 
     218                 :         487 :                 n = cm->ncds * 2;
     219         [ +  - ]:         487 :                 if (n > MAX_COLOR + 1)
     220                 :           0 :                         n = MAX_COLOR + 1;
     221         [ +  + ]:         487 :                 if (cm->cd == cm->cdspace)
     222                 :             :                 {
     223                 :         473 :                         newCd = (struct colordesc *) MALLOC(n * sizeof(struct colordesc));
     224         [ -  + ]:         473 :                         if (newCd != NULL)
     225                 :         473 :                                 memcpy(VS(newCd), VS(cm->cdspace), cm->ncds *
     226                 :             :                                            sizeof(struct colordesc));
     227                 :         473 :                 }
     228                 :             :                 else
     229                 :          14 :                         newCd = (struct colordesc *)
     230                 :          14 :                                 REALLOC(cm->cd, n * sizeof(struct colordesc));
     231         [ +  - ]:         487 :                 if (newCd == NULL)
     232                 :             :                 {
     233         [ #  # ]:           0 :                         CERR(REG_ESPACE);
     234                 :           0 :                         return COLORLESS;
     235                 :             :                 }
     236                 :         487 :                 cm->cd = newCd;
     237                 :         487 :                 cm->ncds = n;
     238         [ +  - ]:         487 :                 assert(cm->max < cm->ncds - 1);
     239                 :         487 :                 cm->max++;
     240                 :         487 :                 cd = &cm->cd[cm->max];
     241         [ -  + ]:         487 :         }
     242                 :             : 
     243                 :        8729 :         cd->nschrs = 0;
     244                 :        8729 :         cd->nuchrs = 0;
     245                 :        8729 :         cd->sub = NOSUB;
     246                 :        8729 :         cd->arcs = NULL;
     247                 :        8729 :         cd->firstchr = CHR_MIN;              /* in case never set otherwise */
     248                 :        8729 :         cd->flags = 0;
     249                 :             : 
     250                 :        8729 :         return (color) (cd - cm->cd);
     251                 :        8729 : }
     252                 :             : 
     253                 :             : /*
     254                 :             :  * freecolor - free a color (must have no arcs or subcolor)
     255                 :             :  */
     256                 :             : static void
     257                 :          27 : freecolor(struct colormap *cm,
     258                 :             :                   color co)
     259                 :             : {
     260                 :          27 :         struct colordesc *cd = &cm->cd[co];
     261                 :          27 :         color           pco,
     262                 :             :                                 nco;                    /* for freelist scan */
     263                 :             : 
     264         [ +  - ]:          27 :         assert(co >= 0);
     265         [ +  - ]:          27 :         if (co == WHITE)
     266                 :           0 :                 return;
     267                 :             : 
     268         [ +  - ]:          27 :         assert(cd->arcs == NULL);
     269         [ +  - ]:          27 :         assert(cd->sub == NOSUB);
     270         [ +  - ]:          27 :         assert(cd->nschrs == 0);
     271         [ +  - ]:          27 :         assert(cd->nuchrs == 0);
     272                 :          27 :         cd->flags = FREECOL;
     273                 :             : 
     274         [ +  + ]:          27 :         if ((size_t) co == cm->max)
     275                 :             :         {
     276   [ -  +  +  + ]:           8 :                 while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max]))
     277                 :           4 :                         cm->max--;
     278         [ +  - ]:           4 :                 assert(cm->free >= 0);
     279         [ -  + ]:           4 :                 while ((size_t) cm->free > cm->max)
     280                 :           0 :                         cm->free = cm->cd[cm->free].sub;
     281         [ +  + ]:           4 :                 if (cm->free > 0)
     282                 :             :                 {
     283         [ +  - ]:           1 :                         assert(cm->free < cm->max);
     284                 :           1 :                         pco = cm->free;
     285                 :           1 :                         nco = cm->cd[pco].sub;
     286         [ -  + ]:           1 :                         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                 :           0 :                                 }
     293                 :             :                                 else
     294                 :             :                                 {
     295         [ #  # ]:           0 :                                         assert(nco < cm->max);
     296                 :           0 :                                         pco = nco;
     297                 :           0 :                                         nco = cm->cd[pco].sub;
     298                 :             :                                 }
     299                 :           1 :                 }
     300                 :           4 :         }
     301                 :             :         else
     302                 :             :         {
     303                 :          23 :                 cd->sub = cm->free;
     304                 :          23 :                 cm->free = (color) (cd - cm->cd);
     305                 :             :         }
     306         [ -  + ]:          27 : }
     307                 :             : 
     308                 :             : /*
     309                 :             :  * pseudocolor - allocate a false color, to be managed by other means
     310                 :             :  */
     311                 :             : static color
     312                 :        3224 : pseudocolor(struct colormap *cm)
     313                 :             : {
     314                 :        3224 :         color           co;
     315                 :        3224 :         struct colordesc *cd;
     316                 :             : 
     317                 :        3224 :         co = newcolor(cm);
     318         [ -  + ]:        3224 :         if (CISERR())
     319                 :           0 :                 return COLORLESS;
     320                 :        3224 :         cd = &cm->cd[co];
     321                 :        3224 :         cd->nschrs = 0;
     322                 :        3224 :         cd->nuchrs = 1;                              /* pretend it is in the upper map */
     323                 :        3224 :         cd->sub = NOSUB;
     324                 :        3224 :         cd->arcs = NULL;
     325                 :        3224 :         cd->firstchr = CHR_MIN;
     326                 :        3224 :         cd->flags = PSEUDO;
     327                 :        3224 :         return co;
     328                 :        3224 : }
     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                 :       40278 : subcolor(struct colormap *cm, chr c)
     337                 :             : {
     338                 :       40278 :         color           co;                             /* current color of c */
     339                 :       40278 :         color           sco;                    /* new subcolor */
     340                 :             : 
     341         [ +  - ]:       40278 :         assert(c <= MAX_SIMPLE_CHR);
     342                 :             : 
     343                 :       40278 :         co = cm->locolormap[c - CHR_MIN];
     344                 :       40278 :         sco = newsub(cm, co);
     345         [ -  + ]:       40278 :         if (CISERR())
     346                 :           0 :                 return COLORLESS;
     347         [ +  - ]:       40278 :         assert(sco != COLORLESS);
     348                 :             : 
     349         [ +  + ]:       40278 :         if (co == sco)                          /* already in an open subcolor */
     350                 :        5109 :                 return co;                              /* rest is redundant */
     351                 :       35169 :         cm->cd[co].nschrs--;
     352         [ +  + ]:       35169 :         if (cm->cd[sco].nschrs == 0)
     353                 :        5502 :                 cm->cd[sco].firstchr = c;
     354                 :       35169 :         cm->cd[sco].nschrs++;
     355                 :       35169 :         cm->locolormap[c - CHR_MIN] = sco;
     356                 :       35169 :         return sco;
     357                 :       40278 : }
     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                 :          81 : subcolorhi(struct colormap *cm, color *pco)
     367                 :             : {
     368                 :          81 :         color           co;                             /* current color of entry */
     369                 :          81 :         color           sco;                    /* new subcolor */
     370                 :             : 
     371                 :          81 :         co = *pco;
     372                 :          81 :         sco = newsub(cm, co);
     373         [ -  + ]:          81 :         if (CISERR())
     374                 :           0 :                 return COLORLESS;
     375         [ +  - ]:          81 :         assert(sco != COLORLESS);
     376                 :             : 
     377         [ -  + ]:          81 :         if (co == sco)                          /* already in an open subcolor */
     378                 :           0 :                 return co;                              /* rest is redundant */
     379                 :          81 :         cm->cd[co].nuchrs--;
     380                 :          81 :         cm->cd[sco].nuchrs++;
     381                 :          81 :         *pco = sco;
     382                 :          81 :         return sco;
     383                 :          81 : }
     384                 :             : 
     385                 :             : /*
     386                 :             :  * newsub - allocate a new subcolor (if necessary) for a color
     387                 :             :  */
     388                 :             : static color
     389                 :       40359 : newsub(struct colormap *cm,
     390                 :             :            color co)
     391                 :             : {
     392                 :       40359 :         color           sco;                    /* new subcolor */
     393                 :             : 
     394                 :       40359 :         sco = cm->cd[co].sub;
     395         [ +  + ]:       40359 :         if (sco == NOSUB)
     396                 :             :         {                                                       /* color has no open subcolor */
     397                 :             :                 /* optimization: singly-referenced color need not be subcolored */
     398         [ +  + ]:       10611 :                 if ((cm->cd[co].nschrs + cm->cd[co].nuchrs) == 1)
     399                 :        5106 :                         return co;
     400                 :        5505 :                 sco = newcolor(cm);             /* must create subcolor */
     401         [ +  - ]:        5505 :                 if (sco == COLORLESS)
     402                 :             :                 {
     403         [ #  # ]:           0 :                         assert(CISERR());
     404                 :           0 :                         return COLORLESS;
     405                 :             :                 }
     406                 :        5505 :                 cm->cd[co].sub = sco;
     407                 :        5505 :                 cm->cd[sco].sub = sco;       /* open subcolor points to self */
     408                 :        5505 :         }
     409         [ +  - ]:       35253 :         assert(sco != NOSUB);
     410                 :             : 
     411                 :       35253 :         return sco;
     412                 :       40359 : }
     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                 :           0 :         color      *newrowptr;
     425                 :           0 :         int                     i;
     426                 :             : 
     427                 :             :         /* Assign a fresh array row index, enlarging storage if needed */
     428         [ #  # ]:           0 :         if (newrow >= cm->maxarrayrows)
     429                 :             :         {
     430                 :           0 :                 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         [ #  # ]:           0 :         }
     448                 :           0 :         cm->hiarrayrows++;
     449                 :             : 
     450                 :             :         /* Copy old row data */
     451                 :           0 :         newrowptr = &cm->hicolormap[newrow * cm->hiarraycols];
     452                 :           0 :         memcpy(newrowptr,
     453                 :             :                    &cm->hicolormap[oldrow * cm->hiarraycols],
     454                 :             :                    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                 :           0 : }
     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                 :          67 : newhicolorcols(struct colormap *cm)
     470                 :             : {
     471                 :          67 :         color      *newarray;
     472                 :          67 :         int                     r,
     473                 :             :                                 c;
     474                 :             : 
     475         [ -  + ]:          67 :         if (cm->hiarraycols >= INT_MAX / (cm->maxarrayrows * 2))
     476                 :             :         {
     477         [ #  # ]:           0 :                 CERR(REG_ESPACE);
     478                 :           0 :                 return;
     479                 :             :         }
     480                 :          67 :         newarray = (color *) REALLOC(cm->hicolormap,
     481                 :             :                                                                  cm->maxarrayrows *
     482                 :             :                                                                  cm->hiarraycols * 2 * sizeof(color));
     483         [ +  - ]:          67 :         if (newarray == NULL)
     484                 :             :         {
     485         [ #  # ]:           0 :                 CERR(REG_ESPACE);
     486                 :           0 :                 return;
     487                 :             :         }
     488                 :          67 :         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         [ +  + ]:         134 :         for (r = cm->hiarrayrows - 1; r >= 0; r--)
     493                 :             :         {
     494                 :          67 :                 color      *oldrowptr = &newarray[r * cm->hiarraycols];
     495                 :          67 :                 color      *newrowptr = &newarray[r * cm->hiarraycols * 2];
     496                 :          67 :                 color      *newrowptr2 = newrowptr + cm->hiarraycols;
     497                 :             : 
     498         [ +  + ]:         137 :                 for (c = 0; c < cm->hiarraycols; c++)
     499                 :             :                 {
     500                 :          70 :                         color           co = oldrowptr[c];
     501                 :             : 
     502                 :          70 :                         newrowptr[c] = newrowptr2[c] = co;
     503                 :          70 :                         cm->cd[co].nuchrs++;
     504                 :          70 :                 }
     505                 :          67 :         }
     506                 :             : 
     507                 :          67 :         cm->hiarraycols *= 2;
     508         [ -  + ]:          67 : }
     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                 :         246 : subcolorcvec(struct vars *v,
     523                 :             :                          struct cvec *cv,
     524                 :             :                          struct state *lp,
     525                 :             :                          struct state *rp)
     526                 :             : {
     527                 :         246 :         struct colormap *cm = v->cm;
     528                 :         246 :         color           lastsubcolor = COLORLESS;
     529                 :         246 :         chr                     ch,
     530                 :             :                                 from,
     531                 :             :                                 to;
     532                 :         246 :         const chr  *p;
     533                 :         246 :         int                     i;
     534                 :             : 
     535                 :             :         /* ordinary characters */
     536         [ +  + ]:        1747 :         for (p = cv->chrs, i = cv->nchrs; i > 0; p++, i--)
     537                 :             :         {
     538                 :        1501 :                 ch = *p;
     539                 :        1501 :                 subcoloronechr(v, ch, lp, rp, &lastsubcolor);
     540         [ -  + ]:        1501 :                 NOERR();
     541                 :        1501 :         }
     542                 :             : 
     543                 :             :         /* and the ranges */
     544         [ +  + ]:        1031 :         for (p = cv->ranges, i = cv->nranges; i > 0; p += 2, i--)
     545                 :             :         {
     546                 :         785 :                 from = *p;
     547                 :         785 :                 to = *(p + 1);
     548         [ -  + ]:         785 :                 if (from <= MAX_SIMPLE_CHR)
     549                 :             :                 {
     550                 :             :                         /* deal with simple chars one at a time */
     551         [ +  - ]:         785 :                         chr                     lim = (to <= MAX_SIMPLE_CHR) ? to : MAX_SIMPLE_CHR;
     552                 :             : 
     553         [ +  + ]:       29206 :                         while (from <= lim)
     554                 :             :                         {
     555                 :       28421 :                                 color           sco = subcolor(cm, from);
     556                 :             : 
     557         [ -  + ]:       28421 :                                 NOERR();
     558         [ +  + ]:       28421 :                                 if (sco != lastsubcolor)
     559                 :             :                                 {
     560                 :         139 :                                         newarc(v->nfa, PLAIN, sco, lp, rp);
     561         [ -  + ]:         139 :                                         NOERR();
     562                 :         139 :                                         lastsubcolor = sco;
     563                 :         139 :                                 }
     564                 :       28421 :                                 from++;
     565         [ -  + ]:       28421 :                         }
     566         [ -  + ]:         785 :                 }
     567                 :             :                 /* deal with any part of the range that's above MAX_SIMPLE_CHR */
     568         [ -  + ]:         785 :                 if (from < to)
     569                 :           0 :                         subcoloronerange(v, from, to, lp, rp, &lastsubcolor);
     570         [ +  - ]:         785 :                 else if (from == to)
     571                 :           0 :                         subcoloronechr(v, from, lp, rp, &lastsubcolor);
     572         [ +  - ]:         785 :                 NOERR();
     573                 :         785 :         }
     574                 :             : 
     575                 :             :         /* and deal with cclass if any */
     576         [ +  + ]:         246 :         if (cv->cclasscode >= 0)
     577                 :             :         {
     578                 :          78 :                 int                     classbit;
     579                 :          78 :                 color      *pco;
     580                 :          78 :                 int                     r,
     581                 :             :                                         c;
     582                 :             : 
     583                 :             :                 /* Enlarge array if we don't have a column bit assignment for cclass */
     584         [ +  + ]:          78 :                 if (cm->classbits[cv->cclasscode] == 0)
     585                 :             :                 {
     586                 :          67 :                         cm->classbits[cv->cclasscode] = cm->hiarraycols;
     587                 :          67 :                         newhicolorcols(cm);
     588         [ +  - ]:          67 :                         NOERR();
     589                 :          67 :                 }
     590                 :             :                 /* Apply subcolorhi() and make arc for each entry in relevant cols */
     591                 :          78 :                 classbit = cm->classbits[cv->cclasscode];
     592                 :          78 :                 pco = cm->hicolormap;
     593         [ +  + ]:         156 :                 for (r = 0; r < cm->hiarrayrows; r++)
     594                 :             :                 {
     595         [ +  + ]:         240 :                         for (c = 0; c < cm->hiarraycols; c++)
     596                 :             :                         {
     597         [ +  + ]:         162 :                                 if (c & classbit)
     598                 :             :                                 {
     599                 :          81 :                                         color           sco = subcolorhi(cm, pco);
     600                 :             : 
     601         [ -  + ]:          81 :                                         NOERR();
     602                 :             :                                         /* add the arc if needed */
     603         [ +  + ]:          81 :                                         if (sco != lastsubcolor)
     604                 :             :                                         {
     605                 :           6 :                                                 newarc(v->nfa, PLAIN, sco, lp, rp);
     606         [ -  + ]:           6 :                                                 NOERR();
     607                 :           6 :                                                 lastsubcolor = sco;
     608                 :           6 :                                         }
     609         [ -  + ]:          81 :                                 }
     610                 :         162 :                                 pco++;
     611                 :         162 :                         }
     612                 :          78 :                 }
     613         [ -  + ]:          78 :         }
     614         [ -  + ]:         246 : }
     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                 :       11834 : subcoloronechr(struct vars *v,
     625                 :             :                            chr ch,
     626                 :             :                            struct state *lp,
     627                 :             :                            struct state *rp,
     628                 :             :                            color *lastsubcolor)
     629                 :             : {
     630                 :       11834 :         struct colormap *cm = v->cm;
     631                 :       11834 :         colormaprange *newranges;
     632                 :       11834 :         int                     numnewranges;
     633                 :       11834 :         colormaprange *oldrange;
     634                 :       11834 :         int                     oldrangen;
     635                 :       11834 :         int                     newrow;
     636                 :             : 
     637                 :             :         /* Easy case for low chr codes */
     638         [ +  - ]:       11834 :         if (ch <= MAX_SIMPLE_CHR)
     639                 :             :         {
     640                 :       11834 :                 color           sco = subcolor(cm, ch);
     641                 :             : 
     642         [ -  + ]:       11834 :                 NOERR();
     643         [ +  + ]:       11834 :                 if (sco != *lastsubcolor)
     644                 :             :                 {
     645                 :       10522 :                         newarc(v->nfa, PLAIN, sco, lp, rp);
     646                 :       10522 :                         *lastsubcolor = sco;
     647                 :       10522 :                 }
     648                 :       11834 :                 return;
     649                 :       11834 :         }
     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                 :           0 :         }
     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                 :           0 :         }
     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                 :           0 :         }
     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                 :           0 :                 }
     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                 :           0 :                                 oldrange->rownum;
     718                 :           0 :                         numnewranges++;
     719                 :           0 :                 }
     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                 :           0 :         }
     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         [ -  + ]:       11834 : }
     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                 :           0 :         colormaprange *newranges;
     756                 :           0 :         int                     numnewranges;
     757                 :           0 :         colormaprange *oldrange;
     758                 :           0 :         int                     oldrangen;
     759                 :           0 :         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                 :           0 :         }
     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                 :           0 :                 }
     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                 :           0 :                 }
     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                 :           0 :                         }
     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                 :           0 :                                         oldrange->rownum;
     843                 :           0 :                                 numnewranges++;
     844                 :           0 :                         }
     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                 :           0 :         }
     864                 :             : 
     865                 :             :         /* Ranges after target are unchanged */
     866         [ #  # ]:           0 :         for (; oldrangen < cm->numcmranges; oldrange++, oldrangen++)
     867                 :             :         {
     868                 :           0 :                 newranges[numnewranges++] = *oldrange;
     869                 :           0 :         }
     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         [ #  # ]:           0 : }
     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                 :           0 :         color      *pco;
     893                 :           0 :         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                 :           0 :                 }
     909         [ #  # ]:           0 :         }
     910         [ #  # ]:           0 : }
     911                 :             : 
     912                 :             : /*
     913                 :             :  * okcolors - promote subcolors to full colors
     914                 :             :  */
     915                 :             : static void
     916                 :       10540 : okcolors(struct nfa *nfa,
     917                 :             :                  struct colormap *cm)
     918                 :             : {
     919                 :       10540 :         struct colordesc *cd;
     920                 :       10540 :         struct colordesc *end = CDEND(cm);
     921                 :       10540 :         struct colordesc *scd;
     922                 :       10540 :         struct arc *a;
     923                 :       10540 :         color           co;
     924                 :       10540 :         color           sco;
     925                 :             : 
     926         [ +  + ]:       76932 :         for (cd = cm->cd, co = 0; cd < end; cd++, co++)
     927                 :             :         {
     928                 :       66392 :                 sco = cd->sub;
     929   [ +  +  +  + ]:       66392 :                 if (UNUSEDCOLOR(cd) || sco == NOSUB)
     930                 :             :                 {
     931                 :             :                         /* has no subcolor, no further action */
     932                 :       60880 :                 }
     933         [ +  + ]:        5512 :                 else if (sco == co)
     934                 :             :                 {
     935                 :             :                         /* is subcolor, let parent deal with it */
     936                 :           7 :                 }
     937   [ +  +  -  + ]:        5505 :                 else if (cd->nschrs == 0 && cd->nuchrs == 0)
     938                 :             :                 {
     939                 :             :                         /*
     940                 :             :                          * Parent is now empty, so just change all its arcs to the
     941                 :             :                          * subcolor, then free the parent.
     942                 :             :                          *
     943                 :             :                          * It is not obvious that simply relabeling the arcs like this is
     944                 :             :                          * OK; it appears to risk creating duplicate arcs.  We are
     945                 :             :                          * basically relying on the assumption that processing of a
     946                 :             :                          * bracket expression can't create arcs of both a color and its
     947                 :             :                          * subcolor between the bracket's endpoints.
     948                 :             :                          */
     949                 :          27 :                         cd->sub = NOSUB;
     950                 :          27 :                         scd = &cm->cd[sco];
     951   [ -  +  #  # ]:          27 :                         assert(scd->nschrs > 0 || scd->nuchrs > 0);
     952         [ +  - ]:          27 :                         assert(scd->sub == sco);
     953                 :          27 :                         scd->sub = NOSUB;
     954         [ +  + ]:          76 :                         while ((a = cd->arcs) != NULL)
     955                 :             :                         {
     956         [ -  + ]:          49 :                                 assert(a->co == co);
     957                 :          49 :                                 uncolorchain(cm, a);
     958                 :          49 :                                 a->co = sco;
     959                 :          49 :                                 colorchain(cm, a);
     960                 :             :                         }
     961                 :          27 :                         freecolor(cm, co);
     962                 :          27 :                 }
     963                 :             :                 else
     964                 :             :                 {
     965                 :             :                         /* parent's arcs must gain parallel subcolor arcs */
     966                 :        5478 :                         cd->sub = NOSUB;
     967                 :        5478 :                         scd = &cm->cd[sco];
     968   [ +  +  +  - ]:        5478 :                         assert(scd->nschrs > 0 || scd->nuchrs > 0);
     969         [ +  - ]:        5478 :                         assert(scd->sub == sco);
     970                 :        5478 :                         scd->sub = NOSUB;
     971         [ +  + ]:        5529 :                         for (a = cd->arcs; a != NULL; a = a->colorchain)
     972                 :             :                         {
     973         [ +  - ]:          51 :                                 assert(a->co == co);
     974                 :          51 :                                 newarc(nfa, a->type, sco, a->from, a->to);
     975                 :          51 :                         }
     976                 :             :                 }
     977                 :       66392 :         }
     978                 :       10540 : }
     979                 :             : 
     980                 :             : /*
     981                 :             :  * colorchain - add this arc to the color chain of its color
     982                 :             :  */
     983                 :             : static void
     984                 :       37925 : colorchain(struct colormap *cm,
     985                 :             :                    struct arc *a)
     986                 :             : {
     987                 :       37925 :         struct colordesc *cd = &cm->cd[a->co];
     988                 :             : 
     989         [ +  - ]:       37925 :         assert(a->co >= 0);
     990         [ +  + ]:       37925 :         if (cd->arcs != NULL)
     991                 :       30323 :                 cd->arcs->colorchainRev = a;
     992                 :       37925 :         a->colorchain = cd->arcs;
     993                 :       37925 :         a->colorchainRev = NULL;
     994                 :       37925 :         cd->arcs = a;
     995                 :       37925 : }
     996                 :             : 
     997                 :             : /*
     998                 :             :  * uncolorchain - delete this arc from the color chain of its color
     999                 :             :  */
    1000                 :             : static void
    1001                 :       22688 : uncolorchain(struct colormap *cm,
    1002                 :             :                          struct arc *a)
    1003                 :             : {
    1004                 :       22688 :         struct colordesc *cd = &cm->cd[a->co];
    1005                 :       22688 :         struct arc *aa = a->colorchainRev;
    1006                 :             : 
    1007         [ +  - ]:       22688 :         assert(a->co >= 0);
    1008         [ +  + ]:       22688 :         if (aa == NULL)
    1009                 :             :         {
    1010         [ +  - ]:        4072 :                 assert(cd->arcs == a);
    1011                 :        4072 :                 cd->arcs = a->colorchain;
    1012                 :        4072 :         }
    1013                 :             :         else
    1014                 :             :         {
    1015         [ +  - ]:       18616 :                 assert(aa->colorchain == a);
    1016                 :       18616 :                 aa->colorchain = a->colorchain;
    1017                 :             :         }
    1018         [ +  + ]:       22688 :         if (a->colorchain != NULL)
    1019                 :       16686 :                 a->colorchain->colorchainRev = aa;
    1020                 :       22688 :         a->colorchain = NULL;                /* paranoia */
    1021                 :       22688 :         a->colorchainRev = NULL;
    1022                 :       22688 : }
    1023                 :             : 
    1024                 :             : /*
    1025                 :             :  * rainbow - add arcs of all full colors (but one) between specified states
    1026                 :             :  *
    1027                 :             :  * If there isn't an exception color, we now generate just a single arc
    1028                 :             :  * labeled RAINBOW, saving lots of arc-munging later on.
    1029                 :             :  */
    1030                 :             : static void
    1031                 :        4477 : rainbow(struct nfa *nfa,
    1032                 :             :                 struct colormap *cm,
    1033                 :             :                 int type,
    1034                 :             :                 color but,                              /* COLORLESS if no exceptions */
    1035                 :             :                 struct state *from,
    1036                 :             :                 struct state *to)
    1037                 :             : {
    1038                 :        4477 :         struct colordesc *cd;
    1039                 :        4477 :         struct colordesc *end = CDEND(cm);
    1040                 :        4477 :         color           co;
    1041                 :             : 
    1042         [ +  + ]:        4477 :         if (but == COLORLESS)
    1043                 :             :         {
    1044                 :        4465 :                 newarc(nfa, type, RAINBOW, from, to);
    1045                 :        4465 :                 return;
    1046                 :             :         }
    1047                 :             : 
    1048                 :             :         /* Gotta do it the hard way.  Skip subcolors, pseudocolors, and "but" */
    1049   [ +  +  +  + ]:          64 :         for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
    1050   [ +  -  +  -  :          52 :                 if (!UNUSEDCOLOR(cd) && cd->sub != co && co != but &&
             +  +  -  + ]
    1051                 :          92 :                         !(cd->flags & PSEUDO))
    1052                 :          40 :                         newarc(nfa, type, co, from, to);
    1053         [ -  + ]:        4477 : }
    1054                 :             : 
    1055                 :             : /*
    1056                 :             :  * colorcomplement - add arcs of complementary colors
    1057                 :             :  *
    1058                 :             :  * We add arcs of all colors that are not pseudocolors and do not match
    1059                 :             :  * any of the "of" state's PLAIN outarcs.
    1060                 :             :  *
    1061                 :             :  * The calling sequence ought to be reconciled with cloneouts().
    1062                 :             :  */
    1063                 :             : static void
    1064                 :          37 : colorcomplement(struct nfa *nfa,
    1065                 :             :                                 struct colormap *cm,
    1066                 :             :                                 int type,
    1067                 :             :                                 struct state *of,
    1068                 :             :                                 struct state *from,
    1069                 :             :                                 struct state *to)
    1070                 :             : {
    1071                 :          37 :         struct colordesc *cd;
    1072                 :          37 :         struct colordesc *end = CDEND(cm);
    1073                 :          37 :         color           co;
    1074                 :          37 :         struct arc *a;
    1075                 :             : 
    1076         [ +  - ]:          37 :         assert(of != from);
    1077                 :             : 
    1078                 :             :         /*
    1079                 :             :          * A RAINBOW arc matches all colors, making the complement empty.  But we
    1080                 :             :          * can't just return without making any arcs, because that would leave the
    1081                 :             :          * NFA disconnected which would break any future delsub().  Instead, make
    1082                 :             :          * a CANTMATCH arc.  Also set the HASCANTMATCH flag so we know we need to
    1083                 :             :          * clean that up at the start of NFA optimization.
    1084                 :             :          */
    1085         [ -  + ]:          37 :         if (findarc(of, PLAIN, RAINBOW) != NULL)
    1086                 :             :         {
    1087                 :           0 :                 newarc(nfa, CANTMATCH, 0, from, to);
    1088                 :           0 :                 nfa->flags |= HASCANTMATCH;
    1089                 :           0 :                 return;
    1090                 :             :         }
    1091                 :             : 
    1092                 :             :         /* Otherwise, transiently mark the colors that appear in of's out-arcs */
    1093         [ +  + ]:          98 :         for (a = of->outs; a != NULL; a = a->outchain)
    1094                 :             :         {
    1095         [ -  + ]:          61 :                 if (a->type == PLAIN)
    1096                 :             :                 {
    1097         [ +  - ]:          61 :                         assert(a->co >= 0);
    1098                 :          61 :                         cd = &cm->cd[a->co];
    1099         [ +  - ]:          61 :                         assert(!UNUSEDCOLOR(cd));
    1100                 :          61 :                         cd->flags |= COLMARK;
    1101                 :          61 :                 }
    1102                 :             : 
    1103                 :             :                 /*
    1104                 :             :                  * There's no syntax for re-complementing a color set, so we cannot
    1105                 :             :                  * see CANTMATCH arcs here.
    1106                 :             :                  */
    1107         [ +  - ]:          61 :                 assert(a->type != CANTMATCH);
    1108                 :          61 :         }
    1109                 :             : 
    1110                 :             :         /* Scan colors, clear transient marks, add arcs for unmarked colors */
    1111   [ +  +  +  + ]:         185 :         for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
    1112                 :             :         {
    1113         [ +  + ]:         148 :                 if (cd->flags & COLMARK)
    1114                 :          61 :                         cd->flags &= ~COLMARK;
    1115   [ +  +  -  + ]:          87 :                 else if (!UNUSEDCOLOR(cd) && !(cd->flags & PSEUDO))
    1116                 :          86 :                         newarc(nfa, type, co, from, to);
    1117                 :         148 :         }
    1118         [ -  + ]:          37 : }
    1119                 :             : 
    1120                 :             : 
    1121                 :             : #ifdef REG_DEBUG
    1122                 :             : 
    1123                 :             : /*
    1124                 :             :  * dumpcolors - debugging output
    1125                 :             :  */
    1126                 :             : static void
    1127                 :             : dumpcolors(struct colormap *cm,
    1128                 :             :                    FILE *f)
    1129                 :             : {
    1130                 :             :         struct colordesc *cd;
    1131                 :             :         struct colordesc *end;
    1132                 :             :         color           co;
    1133                 :             :         chr                     c;
    1134                 :             : 
    1135                 :             :         fprintf(f, "max %ld\n", (long) cm->max);
    1136                 :             :         end = CDEND(cm);
    1137                 :             :         for (cd = cm->cd + 1, co = 1; cd < end; cd++, co++) /* skip 0 */
    1138                 :             :         {
    1139                 :             :                 if (!UNUSEDCOLOR(cd))
    1140                 :             :                 {
    1141                 :             :                         assert(cd->nschrs > 0 || cd->nuchrs > 0);
    1142                 :             :                         if (cd->flags & PSEUDO)
    1143                 :             :                                 fprintf(f, "#%2ld(ps): ", (long) co);
    1144                 :             :                         else
    1145                 :             :                                 fprintf(f, "#%2ld(%2d): ", (long) co, cd->nschrs + cd->nuchrs);
    1146                 :             : 
    1147                 :             :                         /*
    1148                 :             :                          * Unfortunately, it's hard to do this next bit more efficiently.
    1149                 :             :                          */
    1150                 :             :                         for (c = CHR_MIN; c <= MAX_SIMPLE_CHR; c++)
    1151                 :             :                                 if (GETCOLOR(cm, c) == co)
    1152                 :             :                                         dumpchr(c, f);
    1153                 :             :                         fprintf(f, "\n");
    1154                 :             :                 }
    1155                 :             :         }
    1156                 :             :         /* dump the high colormap if it contains anything interesting */
    1157                 :             :         if (cm->hiarrayrows > 1 || cm->hiarraycols > 1)
    1158                 :             :         {
    1159                 :             :                 int                     r,
    1160                 :             :                                         c;
    1161                 :             :                 const color *rowptr;
    1162                 :             : 
    1163                 :             :                 fprintf(f, "other:\t");
    1164                 :             :                 for (c = 0; c < cm->hiarraycols; c++)
    1165                 :             :                 {
    1166                 :             :                         fprintf(f, "\t%ld", (long) cm->hicolormap[c]);
    1167                 :             :                 }
    1168                 :             :                 fprintf(f, "\n");
    1169                 :             :                 for (r = 0; r < cm->numcmranges; r++)
    1170                 :             :                 {
    1171                 :             :                         dumpchr(cm->cmranges[r].cmin, f);
    1172                 :             :                         fprintf(f, "..");
    1173                 :             :                         dumpchr(cm->cmranges[r].cmax, f);
    1174                 :             :                         fprintf(f, ":");
    1175                 :             :                         rowptr = &cm->hicolormap[cm->cmranges[r].rownum * cm->hiarraycols];
    1176                 :             :                         for (c = 0; c < cm->hiarraycols; c++)
    1177                 :             :                         {
    1178                 :             :                                 fprintf(f, "\t%ld", (long) rowptr[c]);
    1179                 :             :                         }
    1180                 :             :                         fprintf(f, "\n");
    1181                 :             :                 }
    1182                 :             :         }
    1183                 :             : }
    1184                 :             : 
    1185                 :             : /*
    1186                 :             :  * dumpchr - print a chr
    1187                 :             :  *
    1188                 :             :  * Kind of char-centric but works well enough for debug use.
    1189                 :             :  */
    1190                 :             : static void
    1191                 :             : dumpchr(chr c,
    1192                 :             :                 FILE *f)
    1193                 :             : {
    1194                 :             :         if (c == '\\')
    1195                 :             :                 fprintf(f, "\\\\");
    1196                 :             :         else if (c > ' ' && c <= '~')
    1197                 :             :                 putc((char) c, f);
    1198                 :             :         else
    1199                 :             :                 fprintf(f, "\\u%04lx", (long) c);
    1200                 :             : }
    1201                 :             : 
    1202                 :             : #endif                                                  /* REG_DEBUG */
        

Generated by: LCOV version 2.3.2-1