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