YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

/Users/deen/code/yugabyte-db/src/postgres/src/backend/regex/regc_color.c
Line
Count
Source (jump to first uncovered line)
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
49.8k
#define CISERR()  VISERR(cm->v)
41
0
#define CERR(e)   VERR(cm->v, (e))
42
43
44
45
/*
46
 * initcm - set up new colormap
47
 */
48
static void
49
initcm(struct vars *v,
50
     struct colormap *cm)
51
325
{
52
325
  struct colordesc *cd;
53
54
325
  cm->magic = CMMAGIC;
55
325
  cm->v = v;
56
57
325
  cm->ncds = NINLINECDS;
58
325
  cm->cd = cm->cdspace;
59
325
  cm->max = 0;
60
325
  cm->free = 0;
61
62
325
  cd = cm->cd;        /* cm->cd[WHITE] */
63
325
  cd->nschrs = MAX_SIMPLE_CHR - CHR_MIN + 1;
64
325
  cd->nuchrs = 1;
65
325
  cd->sub = NOSUB;
66
325
  cd->arcs = NULL;
67
325
  cd->firstchr = CHR_MIN;
68
325
  cd->flags = 0;
69
70
325
  cm->locolormap = (color *)
71
325
    MALLOC((MAX_SIMPLE_CHR - CHR_MIN + 1) * sizeof(color));
72
325
  if (cm->locolormap == NULL)
73
0
  {
74
0
    CERR(REG_ESPACE);
75
0
    cm->cmranges = NULL;  /* prevent failure during freecm */
76
0
    cm->hicolormap = NULL;
77
0
    return;
78
0
  }
79
  /* this memset relies on WHITE being zero: */
80
325
  memset(cm->locolormap, WHITE,
81
325
       (MAX_SIMPLE_CHR - CHR_MIN + 1) * sizeof(color));
82
83
325
  memset(cm->classbits, 0, sizeof(cm->classbits));
84
325
  cm->numcmranges = 0;
85
325
  cm->cmranges = NULL;
86
325
  cm->maxarrayrows = 4;   /* arbitrary initial allocation */
87
325
  cm->hiarrayrows = 1;    /* but we have only one row/col initially */
88
325
  cm->hiarraycols = 1;
89
325
  cm->hicolormap = (color *) MALLOC(cm->maxarrayrows * sizeof(color));
90
325
  if (cm->hicolormap == NULL)
91
0
  {
92
0
    CERR(REG_ESPACE);
93
0
    return;
94
0
  }
95
  /* initialize the "all other characters" row to WHITE */
96
325
  cm->hicolormap[0] = WHITE;
97
325
}
98
99
/*
100
 * freecm - free dynamically-allocated things in a colormap
101
 */
102
static void
103
freecm(struct colormap *cm)
104
43
{
105
43
  cm->magic = 0;
106
43
  if (cm->cd != cm->cdspace)
107
7
    FREE(cm->cd);
108
43
  if (cm->locolormap != NULL)
109
43
    FREE(cm->locolormap);
110
43
  if (cm->cmranges != NULL)
111
0
    FREE(cm->cmranges);
112
43
  if (cm->hicolormap != NULL)
113
43
    FREE(cm->hicolormap);
114
43
}
115
116
/*
117
 * pg_reg_getcolor - slow case of GETCOLOR()
118
 */
119
color
120
pg_reg_getcolor(struct colormap *cm, chr c)
121
17
{
122
17
  int     rownum,
123
17
        colnum,
124
17
        low,
125
17
        high;
126
127
  /* Should not be used for chrs in the locolormap */
128
17
  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
17
  rownum = 0;         /* if no match, use array row zero */
135
17
  low = 0;
136
17
  high = cm->numcmranges;
137
17
  while (low < high)
138
0
  {
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
0
    else
147
0
    {
148
0
      rownum = cmr->rownum; /* found a match */
149
0
      break;
150
0
    }
151
0
  }
152
153
  /*
154
   * Find which column it's in --- this is all locale-dependent.
155
   */
156
17
  if (cm->hiarraycols > 1)
157
0
  {
158
0
    colnum = cclass_column_index(cm, c);
159
0
    return cm->hicolormap[rownum * cm->hiarraycols + colnum];
160
0
  }
161
17
  else
162
17
  {
163
    /* fast path if no relevant cclasses */
164
17
    return cm->hicolormap[rownum];
165
17
  }
166
17
}
167
168
/*
169
 * maxcolor - report largest color number in use
170
 */
171
static color
172
maxcolor(struct colormap *cm)
173
1.41k
{
174
1.41k
  if (CISERR())
175
0
    return COLORLESS;
176
177
1.41k
  return (color) cm->max;
178
1.41k
}
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
newcolor(struct colormap *cm)
186
3.41k
{
187
3.41k
  struct colordesc *cd;
188
3.41k
  size_t    n;
189
190
3.41k
  if (CISERR())
191
0
    return COLORLESS;
192
193
3.41k
  if (cm->free != 0)
194
39
  {
195
39
    assert(cm->free > 0);
196
39
    assert((size_t) cm->free < cm->ncds);
197
39
    cd = &cm->cd[cm->free];
198
39
    assert(UNUSEDCOLOR(cd));
199
39
    assert(cd->arcs == NULL);
200
39
    cm->free = cd->sub;
201
39
  }
202
3.37k
  else if (cm->max < cm->ncds - 1)
203
3.17k
  {
204
3.17k
    cm->max++;
205
3.17k
    cd = &cm->cd[cm->max];
206
3.17k
  }
207
200
  else
208
200
  {
209
    /* oops, must allocate more */
210
200
    struct colordesc *newCd;
211
212
200
    if (cm->max == MAX_COLOR)
213
0
    {
214
0
      CERR(REG_ECOLORS);
215
0
      return COLORLESS; /* too many colors */
216
0
    }
217
218
200
    n = cm->ncds * 2;
219
200
    if (n > MAX_COLOR + 1)
220
0
      n = MAX_COLOR + 1;
221
200
    if (cm->cd == cm->cdspace)
222
197
    {
223
197
      newCd = (struct colordesc *) MALLOC(n * sizeof(struct colordesc));
224
197
      if (newCd != NULL)
225
197
        memcpy(VS(newCd), VS(cm->cdspace), cm->ncds *
226
197
             sizeof(struct colordesc));
227
197
    }
228
3
    else
229
3
      newCd = (struct colordesc *)
230
3
        REALLOC(cm->cd, n * sizeof(struct colordesc));
231
200
    if (newCd == NULL)
232
0
    {
233
0
      CERR(REG_ESPACE);
234
0
      return COLORLESS;
235
0
    }
236
200
    cm->cd = newCd;
237
200
    cm->ncds = n;
238
200
    assert(cm->max < cm->ncds - 1);
239
200
    cm->max++;
240
200
    cd = &cm->cd[cm->max];
241
200
  }
242
243
3.41k
  cd->nschrs = 0;
244
3.41k
  cd->nuchrs = 0;
245
3.41k
  cd->sub = NOSUB;
246
3.41k
  cd->arcs = NULL;
247
3.41k
  cd->firstchr = CHR_MIN;   /* in case never set otherwise */
248
3.41k
  cd->flags = 0;
249
250
3.41k
  return (color) (cd - cm->cd);
251
3.41k
}
252
253
/*
254
 * freecolor - free a color (must have no arcs or subcolor)
255
 */
256
static void
257
freecolor(struct colormap *cm,
258
      color co)
259
41
{
260
41
  struct colordesc *cd = &cm->cd[co];
261
41
  color   pco,
262
41
        nco;      /* for freelist scan */
263
264
41
  assert(co >= 0);
265
41
  if (co == WHITE)
266
0
    return;
267
268
41
  assert(cd->arcs == NULL);
269
41
  assert(cd->sub == NOSUB);
270
41
  assert(cd->nschrs == 0);
271
41
  assert(cd->nuchrs == 0);
272
41
  cd->flags = FREECOL;
273
274
41
  if ((size_t) co == cm->max)
275
1
  {
276
3
    while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max]))
277
2
      cm->max--;
278
1
    assert(cm->free >= 0);
279
2
    
while (1
(size_t) cm->free > cm->max)
280
1
      cm->free = cm->cd[cm->free].sub;
281
1
    if (cm->free > 0)
282
0
    {
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
0
        {
289
          /* take this one out of freelist */
290
0
          nco = cm->cd[nco].sub;
291
0
          cm->cd[pco].sub = nco;
292
0
        }
293
0
        else
294
0
        {
295
0
          assert(nco < cm->max);
296
0
          pco = nco;
297
0
          nco = cm->cd[pco].sub;
298
0
        }
299
0
    }
300
1
  }
301
40
  else
302
40
  {
303
40
    cd->sub = cm->free;
304
40
    cm->free = (color) (cd - cm->cd);
305
40
  }
306
41
}
307
308
/*
309
 * pseudocolor - allocate a false color, to be managed by other means
310
 */
311
static color
312
pseudocolor(struct colormap *cm)
313
1.29k
{
314
1.29k
  color   co;
315
1.29k
  struct colordesc *cd;
316
317
1.29k
  co = newcolor(cm);
318
1.29k
  if (CISERR())
319
0
    return COLORLESS;
320
1.29k
  cd = &cm->cd[co];
321
1.29k
  cd->nschrs = 0;
322
1.29k
  cd->nuchrs = 1;       /* pretend it is in the upper map */
323
1.29k
  cd->sub = NOSUB;
324
1.29k
  cd->arcs = NULL;
325
1.29k
  cd->firstchr = CHR_MIN;
326
1.29k
  cd->flags = PSEUDO;
327
1.29k
  return co;
328
1.29k
}
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
subcolor(struct colormap *cm, chr c)
337
11.7k
{
338
11.7k
  color   co;       /* current color of c */
339
11.7k
  color   sco;      /* new subcolor */
340
341
11.7k
  assert(c <= MAX_SIMPLE_CHR);
342
343
11.7k
  co = cm->locolormap[c - CHR_MIN];
344
11.7k
  sco = newsub(cm, co);
345
11.7k
  if (CISERR())
346
0
    return COLORLESS;
347
11.7k
  assert(sco != COLORLESS);
348
349
11.7k
  if (co == sco)        /* already in an open subcolor */
350
630
    return co;        /* rest is redundant */
351
11.0k
  cm->cd[co].nschrs--;
352
11.0k
  if (cm->cd[sco].nschrs == 0)
353
2.11k
    cm->cd[sco].firstchr = c;
354
11.0k
  cm->cd[sco].nschrs++;
355
11.0k
  cm->locolormap[c - CHR_MIN] = sco;
356
11.0k
  return sco;
357
11.7k
}
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
subcolorhi(struct colormap *cm, color *pco)
367
38
{
368
38
  color   co;       /* current color of entry */
369
38
  color   sco;      /* new subcolor */
370
371
38
  co = *pco;
372
38
  sco = newsub(cm, co);
373
38
  if (CISERR())
374
0
    return COLORLESS;
375
38
  assert(sco != COLORLESS);
376
377
38
  if (co == sco)        /* already in an open subcolor */
378
0
    return co;       /* rest is redundant */
379
38
  cm->cd[co].nuchrs--;
380
38
  cm->cd[sco].nuchrs++;
381
38
  *pco = sco;
382
38
  return sco;
383
38
}
384
385
/*
386
 * newsub - allocate a new subcolor (if necessary) for a color
387
 */
388
static color
389
newsub(struct colormap *cm,
390
     color co)
391
11.7k
{
392
11.7k
  color   sco;      /* new subcolor */
393
394
11.7k
  sco = cm->cd[co].sub;
395
11.7k
  if (sco == NOSUB)
396
2.74k
  {             /* color has no open subcolor */
397
    /* optimization: singly-referenced color need not be subcolored */
398
2.74k
    if ((cm->cd[co].nschrs + cm->cd[co].nuchrs) == 1)
399
630
      return co;
400
2.11k
    sco = newcolor(cm);   /* must create subcolor */
401
2.11k
    if (sco == COLORLESS)
402
0
    {
403
0
      assert(CISERR());
404
0
      return COLORLESS;
405
0
    }
406
2.11k
    cm->cd[co].sub = sco;
407
2.11k
    cm->cd[sco].sub = sco;  /* open subcolor points to self */
408
2.11k
  }
409
11.1k
  assert(sco != NOSUB);
410
411
11.1k
  return sco;
412
11.1k
}
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
newhicolorrow(struct colormap *cm,
421
        int oldrow)
422
0
{
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
0
  {
430
0
    color    *newarray;
431
432
0
    if (cm->maxarrayrows >= INT_MAX / (cm->hiarraycols * 2))
433
0
    {
434
0
      CERR(REG_ESPACE);
435
0
      return 0;
436
0
    }
437
0
    newarray = (color *) REALLOC(cm->hicolormap,
438
0
                   cm->maxarrayrows * 2 *
439
0
                   cm->hiarraycols * sizeof(color));
440
0
    if (newarray == NULL)
441
0
    {
442
0
      CERR(REG_ESPACE);
443
0
      return 0;
444
0
    }
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
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
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
newhicolorcols(struct colormap *cm)
470
27
{
471
27
  color    *newarray;
472
27
  int     r,
473
27
        c;
474
475
27
  if (cm->hiarraycols >= INT_MAX / (cm->maxarrayrows * 2))
476
0
  {
477
0
    CERR(REG_ESPACE);
478
0
    return;
479
0
  }
480
27
  newarray = (color *) REALLOC(cm->hicolormap,
481
27
                 cm->maxarrayrows *
482
27
                 cm->hiarraycols * 2 * sizeof(color));
483
27
  if (newarray == NULL)
484
0
  {
485
0
    CERR(REG_ESPACE);
486
0
    return;
487
0
  }
488
27
  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
54
  for (r = cm->hiarrayrows - 1; r >= 0; 
r--27
)
493
27
  {
494
27
    color    *oldrowptr = &newarray[r * cm->hiarraycols];
495
27
    color    *newrowptr = &newarray[r * cm->hiarraycols * 2];
496
27
    color    *newrowptr2 = newrowptr + cm->hiarraycols;
497
498
54
    for (c = 0; c < cm->hiarraycols; 
c++27
)
499
27
    {
500
27
      color   co = oldrowptr[c];
501
502
27
      newrowptr[c] = newrowptr2[c] = co;
503
27
      cm->cd[co].nuchrs++;
504
27
    }
505
27
  }
506
507
27
  cm->hiarraycols *= 2;
508
27
}
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
subcolorcvec(struct vars *v,
523
       struct cvec *cv,
524
       struct state *lp,
525
       struct state *rp)
526
344
{
527
344
  struct colormap *cm = v->cm;
528
344
  color   lastsubcolor = COLORLESS;
529
344
  chr     ch,
530
344
        from,
531
344
        to;
532
344
  const chr  *p;
533
344
  int     i;
534
535
  /* ordinary characters */
536
1.51k
  for (p = cv->chrs, i = cv->nchrs; i > 0; 
p++, i--1.17k
)
537
1.17k
  {
538
1.17k
    ch = *p;
539
1.17k
    subcoloronechr(v, ch, lp, rp, &lastsubcolor);
540
1.17k
    NOERR();
541
1.17k
  }
542
543
  /* and the ranges */
544
583
  
for (p = cv->ranges, i = cv->nranges; 344
i > 0;
p += 2, i--239
)
545
239
  {
546
239
    from = *p;
547
239
    to = *(p + 1);
548
239
    if (from <= MAX_SIMPLE_CHR)
549
239
    {
550
      /* deal with simple chars one at a time */
551
239
      chr     lim = (to <= MAX_SIMPLE_CHR) ? to : 
MAX_SIMPLE_CHR0
;
552
553
8.40k
      while (from <= lim)
554
8.16k
      {
555
8.16k
        color   sco = subcolor(cm, from);
556
557
8.16k
        NOERR();
558
8.16k
        if (sco != lastsubcolor)
559
218
        {
560
218
          newarc(v->nfa, PLAIN, sco, lp, rp);
561
218
          NOERR();
562
218
          lastsubcolor = sco;
563
218
        }
564
8.16k
        from++;
565
8.16k
      }
566
239
    }
567
    /* deal with any part of the range that's above MAX_SIMPLE_CHR */
568
239
    if (from < to)
569
0
      subcoloronerange(v, from, to, lp, rp, &lastsubcolor);
570
239
    else if (from == to)
571
0
      subcoloronechr(v, from, lp, rp, &lastsubcolor);
572
239
    NOERR();
573
239
  }
574
575
  /* and deal with cclass if any */
576
344
  if (cv->cclasscode >= 0)
577
38
  {
578
38
    int     classbit;
579
38
    color    *pco;
580
38
    int     r,
581
38
          c;
582
583
    /* Enlarge array if we don't have a column bit assignment for cclass */
584
38
    if (cm->classbits[cv->cclasscode] == 0)
585
27
    {
586
27
      cm->classbits[cv->cclasscode] = cm->hiarraycols;
587
27
      newhicolorcols(cm);
588
27
      NOERR();
589
27
    }
590
    /* Apply subcolorhi() and make arc for each entry in relevant cols */
591
38
    classbit = cm->classbits[cv->cclasscode];
592
38
    pco = cm->hicolormap;
593
76
    for (r = 0; r < cm->hiarrayrows; 
r++38
)
594
38
    {
595
114
      for (c = 0; c < cm->hiarraycols; 
c++76
)
596
76
      {
597
76
        if (c & classbit)
598
38
        {
599
38
          color   sco = subcolorhi(cm, pco);
600
601
38
          NOERR();
602
          /* add the arc if needed */
603
38
          if (sco != lastsubcolor)
604
0
          {
605
0
            newarc(v->nfa, PLAIN, sco, lp, rp);
606
0
            NOERR();
607
0
            lastsubcolor = sco;
608
0
          }
609
38
        }
610
76
        pco++;
611
76
      }
612
38
    }
613
38
  }
614
344
}
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
subcoloronechr(struct vars *v,
625
         chr ch,
626
         struct state *lp,
627
         struct state *rp,
628
         color *lastsubcolor)
629
3.49k
{
630
3.49k
  struct colormap *cm = v->cm;
631
3.49k
  colormaprange *newranges;
632
3.49k
  int     numnewranges;
633
3.49k
  colormaprange *oldrange;
634
3.49k
  int     oldrangen;
635
3.49k
  int     newrow;
636
637
  /* Easy case for low chr codes */
638
3.49k
  if (ch <= MAX_SIMPLE_CHR)
639
3.49k
  {
640
3.49k
    color   sco = subcolor(cm, ch);
641
642
3.49k
    NOERR();
643
3.49k
    if (sco != *lastsubcolor)
644
2.61k
    {
645
2.61k
      newarc(v->nfa, PLAIN, sco, lp, rp);
646
2.61k
      *lastsubcolor = sco;
647
2.61k
    }
648
3.49k
    return;
649
3.49k
  }
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
0
  {
659
0
    CERR(REG_ESPACE);
660
0
    return;
661
0
  }
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
0
  {
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
0
  {
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
0
  {
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
0
  else
693
0
  {
694
    /* chr is a subset of this existing range, must split it */
695
0
    if (ch > oldrange->cmin)
696
0
    {
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
0
    {
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
0
  }
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
0
  {
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
0
}
742
743
/*
744
 * subcoloronerange - do subcolorcvec's work for a high range
745
 */
746
static void
747
subcoloronerange(struct vars *v,
748
         chr from,
749
         chr to,
750
         struct state *lp,
751
         struct state *rp,
752
         color *lastsubcolor)
753
0
{
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
0
  {
773
0
    CERR(REG_ESPACE);
774
0
    return;
775
0
  }
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
0
  {
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
0
  {
795
0
    if (from < oldrange->cmin)
796
0
    {
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
0
    {
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
0
    else
817
0
    {
818
      /* some part of old range does not overlap new range */
819
0
      if (from > oldrange->cmin)
820
0
      {
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
0
      {
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
0
    }
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
0
  }
852
853
0
  if (from <= to)
854
0
  {
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
0
  {
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
subcoloronerow(struct vars *v,
886
         int rownum,
887
         struct state *lp,
888
         struct state *rp,
889
         color *lastsubcolor)
890
0
{
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
0
  {
899
0
    color   sco = subcolorhi(cm, pco);
900
901
0
    NOERR();
902
    /* make the arc if needed */
903
0
    if (sco != *lastsubcolor)
904
0
    {
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
okcolors(struct nfa *nfa,
917
     struct colormap *cm)
918
2.64k
{
919
2.64k
  struct colordesc *cd;
920
2.64k
  struct colordesc *end = CDEND(cm);
921
2.64k
  struct colordesc *scd;
922
2.64k
  struct arc *a;
923
2.64k
  color   co;
924
2.64k
  color   sco;
925
926
20.0k
  for (cd = cm->cd, co = 0; cd < end; 
cd++, co++17.4k
)
927
17.4k
  {
928
17.4k
    sco = cd->sub;
929
17.4k
    if (UNUSEDCOLOR(cd) || 
sco == 17.4k
NOSUB17.4k
)
930
15.3k
    {
931
      /* has no subcolor, no further action */
932
15.3k
    }
933
2.12k
    else if (sco == co)
934
2
    {
935
      /* is subcolor, let parent deal with it */
936
2
    }
937
2.11k
    else if (cd->nschrs == 0 && 
cd->nuchrs == 042
)
938
41
    {
939
      /* parent empty, its arcs change color to subcolor */
940
41
      cd->sub = NOSUB;
941
41
      scd = &cm->cd[sco];
942
41
      assert(scd->nschrs > 0 || scd->nuchrs > 0);
943
41
      assert(scd->sub == sco);
944
41
      scd->sub = NOSUB;
945
173
      while ((a = cd->arcs) != NULL)
946
132
      {
947
132
        assert(a->co == co);
948
132
        uncolorchain(cm, a);
949
132
        a->co = sco;
950
132
        colorchain(cm, a);
951
132
      }
952
41
      freecolor(cm, co);
953
41
    }
954
2.07k
    else
955
2.07k
    {
956
      /* parent's arcs must gain parallel subcolor arcs */
957
2.07k
      cd->sub = NOSUB;
958
2.07k
      scd = &cm->cd[sco];
959
2.07k
      assert(scd->nschrs > 0 || scd->nuchrs > 0);
960
2.07k
      assert(scd->sub == sco);
961
2.07k
      scd->sub = NOSUB;
962
6.84k
      for (a = cd->arcs; a != NULL; 
a = a->colorchain4.76k
)
963
4.76k
      {
964
4.76k
        assert(a->co == co);
965
4.76k
        newarc(nfa, a->type, sco, a->from, a->to);
966
4.76k
      }
967
2.07k
    }
968
17.4k
  }
969
2.64k
}
970
971
/*
972
 * colorchain - add this arc to the color chain of its color
973
 */
974
static void
975
colorchain(struct colormap *cm,
976
       struct arc *a)
977
20.7k
{
978
20.7k
  struct colordesc *cd = &cm->cd[a->co];
979
980
20.7k
  if (cd->arcs != NULL)
981
17.3k
    cd->arcs->colorchainRev = a;
982
20.7k
  a->colorchain = cd->arcs;
983
20.7k
  a->colorchainRev = NULL;
984
20.7k
  cd->arcs = a;
985
20.7k
}
986
987
/*
988
 * uncolorchain - delete this arc from the color chain of its color
989
 */
990
static void
991
uncolorchain(struct colormap *cm,
992
       struct arc *a)
993
11.9k
{
994
11.9k
  struct colordesc *cd = &cm->cd[a->co];
995
11.9k
  struct arc *aa = a->colorchainRev;
996
997
11.9k
  if (aa == NULL)
998
2.46k
  {
999
2.46k
    assert(cd->arcs == a);
1000
2.46k
    cd->arcs = a->colorchain;
1001
2.46k
  }
1002
9.53k
  else
1003
9.53k
  {
1004
9.53k
    assert(aa->colorchain == a);
1005
9.53k
    aa->colorchain = a->colorchain;
1006
9.53k
  }
1007
11.9k
  if (a->colorchain != NULL)
1008
7.75k
    a->colorchain->colorchainRev = aa;
1009
11.9k
  a->colorchain = NULL;   /* paranoia */
1010
11.9k
  a->colorchainRev = NULL;
1011
11.9k
}
1012
1013
/*
1014
 * rainbow - add arcs of all full colors (but one) between specified states
1015
 */
1016
static void
1017
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
3.05k
{
1024
3.05k
  struct colordesc *cd;
1025
3.05k
  struct colordesc *end = CDEND(cm);
1026
3.05k
  color   co;
1027
1028
35.0k
  for (cd = cm->cd, co = 0; cd < end && 
!31.9k
CISERR31.9k
();
cd++, co++31.9k
)
1029
31.9k
    if (!UNUSEDCOLOR(cd) && cd->sub != co && co != but &&
1030
31.9k
      
!(cd->flags & 31.9k
PSEUDO31.9k
))
1031
22.5k
      newarc(nfa, type, co, from, to);
1032
3.05k
}
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
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
6
{
1047
6
  struct colordesc *cd;
1048
6
  struct colordesc *end = CDEND(cm);
1049
6
  color   co;
1050
1051
6
  assert(of != from);
1052
23
  
for (cd = cm->cd, co = 0; 6
cd < end &&
!17
CISERR17
();
cd++, co++17
)
1053
17
    if (!UNUSEDCOLOR(cd) && !(cd->flags & PSEUDO))
1054
17
      if (findarc(of, PLAIN, co) == NULL)
1055
11
        newarc(nfa, type, co, from, to);
1056
6
}
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 */