]>
git.saurik.com Git - wxWidgets.git/blob - src/regex/regc_color.c
2 * colorings of characters
3 * This file is #included by regcomp.c.
5 * Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
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
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.
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.
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.
34 * Note that there are some incestuous relationships between this code and
35 * NFA arc maintenance, which perhaps ought to be cleaned up sometime.
40 #define CISERR() VISERR(cm->v)
41 #define CERR(e) VERR(cm->v, (e))
46 * initcm - set up new colormap
49 initcm(struct vars
* v
,
61 cm
->ncds
= NINLINECDS
;
66 cd
= cm
->cd
; /* cm->cd[WHITE] */
70 cd
->nchrs
= CHR_MAX
- CHR_MIN
+ 1;
72 /* upper levels of tree */
73 for (t
= &cm
->tree
[0], j
= NBYTS
- 1; j
> 0; t
= nextt
, j
--)
76 for (i
= BYTTAB
- 1; i
>= 0; i
--)
79 /* bottom level is solid white */
80 t
= &cm
->tree
[NBYTS
- 1];
81 for (i
= BYTTAB
- 1; i
>= 0; i
--)
87 * freecm - free dynamically-allocated things in a colormap
90 freecm(struct colormap
* cm
)
97 cmtreefree(cm
, cm
->tree
, 0);
98 for (i
= 1; i
<= cm
->max
; i
++) /* skip WHITE */
99 if (!UNUSEDCOLOR(&cm
->cd
[i
]))
101 cb
= cm
->cd
[i
].block
;
105 if (cm
->cd
!= cm
->cdspace
)
110 * cmtreefree - free a non-terminal part of a colormap tree
113 cmtreefree(struct colormap
* cm
,
115 int level
) /* level number (top == 0) of this block */
119 union tree
*fillt
= &cm
->tree
[level
+ 1];
122 assert(level
< NBYTS
- 1); /* this level has pointers */
123 for (i
= BYTTAB
- 1; i
>= 0; i
--)
129 if (level
< NBYTS
- 2)
130 { /* more pointer blocks below */
131 cmtreefree(cm
, t
, level
+ 1);
135 { /* color block below */
136 cb
= cm
->cd
[t
->tcolor
[0]].block
;
137 if (t
!= cb
) /* not a solid block */
145 * setcolor - set the color of a character in a colormap
147 static color
/* previous color */
148 setcolor(struct colormap
* cm
,
164 assert(cm
->magic
== CMMAGIC
);
165 if (CISERR() || co
== COLORLESS
)
169 for (level
= 0, shift
= BYTBITS
* (NBYTS
- 1); shift
> 0;
170 level
++, shift
-= BYTBITS
)
172 b
= (uc
>> shift
) & BYTMASK
;
176 fillt
= &cm
->tree
[level
+ 1];
177 bottom
= (shift
<= BYTBITS
) ? 1 : 0;
178 cb
= (bottom
) ? cm
->cd
[t
->tcolor
[0]].block
: fillt
;
179 if (t
== fillt
|| t
== cb
)
180 { /* must allocate a new block */
181 newt
= (union tree
*) MALLOC((bottom
) ?
182 sizeof(struct colors
) : sizeof(struct ptrs
));
189 memcpy(VS(newt
->tcolor
), VS(t
->tcolor
),
190 BYTTAB
* sizeof(color
));
192 memcpy(VS(newt
->tptr
), VS(t
->tptr
),
193 BYTTAB
* sizeof(union tree
*));
201 t
->tcolor
[b
] = (color
) co
;
206 * maxcolor - report largest color number in use
209 maxcolor(struct colormap
* cm
)
214 return (color
) cm
->max
;
218 * newcolor - find a new color (must be subject of setcolor at once)
219 * Beware: may relocate the colordescs.
221 static color
/* COLORLESS for error */
222 newcolor(struct colormap
* cm
)
224 struct colordesc
*cd
;
225 struct colordesc
*new;
233 assert(cm
->free
> 0);
234 assert((size_t) cm
->free
< cm
->ncds
);
235 cd
= &cm
->cd
[cm
->free
];
236 assert(UNUSEDCOLOR(cd
));
237 assert(cd
->arcs
== NULL
);
240 else if (cm
->max
< cm
->ncds
- 1)
243 cd
= &cm
->cd
[cm
->max
];
247 /* oops, must allocate more */
249 if (cm
->cd
== cm
->cdspace
)
251 new = (struct colordesc
*) MALLOC(n
*
252 sizeof(struct colordesc
));
254 memcpy(VS(new), VS(cm
->cdspace
), cm
->ncds
*
255 sizeof(struct colordesc
));
258 new = (struct colordesc
*) REALLOC(cm
->cd
,
259 n
* sizeof(struct colordesc
));
267 assert(cm
->max
< cm
->ncds
- 1);
269 cd
= &cm
->cd
[cm
->max
];
278 return (color
) (cd
- cm
->cd
);
282 * freecolor - free a color (must have no arcs or subcolor)
285 freecolor(struct colormap
* cm
,
288 struct colordesc
*cd
= &cm
->cd
[co
];
290 nco
; /* for freelist scan */
296 assert(cd
->arcs
== NULL
);
297 assert(cd
->sub
== NOSUB
);
298 assert(cd
->nchrs
== 0);
300 if (cd
->block
!= NULL
)
303 cd
->block
= NULL
; /* just paranoia */
306 if ((size_t) co
== cm
->max
)
308 while (cm
->max
> WHITE
&& UNUSEDCOLOR(&cm
->cd
[cm
->max
]))
310 assert(cm
->free
>= 0);
311 while ((size_t) cm
->free
> cm
->max
)
312 cm
->free
= cm
->cd
[cm
->free
].sub
;
315 assert(cm
->free
< cm
->max
);
317 nco
= cm
->cd
[pco
].sub
;
319 if ((size_t) nco
> cm
->max
)
321 /* take this one out of freelist */
322 nco
= cm
->cd
[nco
].sub
;
323 cm
->cd
[pco
].sub
= nco
;
327 assert(nco
< cm
->max
);
329 nco
= cm
->cd
[pco
].sub
;
336 cm
->free
= (color
) (cd
- cm
->cd
);
341 * pseudocolor - allocate a false color, to be managed by other means
344 pseudocolor(struct colormap
* cm
)
351 cm
->cd
[co
].nchrs
= 1;
352 cm
->cd
[co
].flags
= PSEUDO
;
357 * subcolor - allocate a new subcolor (if necessary) to this chr
360 subcolor(struct colormap
* cm
, chr c
)
362 color co
; /* current color of c */
363 color sco
; /* new subcolor */
365 co
= GETCOLOR(cm
, c
);
366 sco
= newsub(cm
, co
);
369 assert(sco
!= COLORLESS
);
371 if (co
== sco
) /* already in an open subcolor */
372 return co
; /* rest is redundant */
375 setcolor(cm
, c
, sco
);
380 * newsub - allocate a new subcolor (if necessary) for a color
383 newsub(struct colormap
* cm
,
386 color sco
; /* new subcolor */
388 sco
= cm
->cd
[co
].sub
;
390 { /* color has no open subcolor */
391 if (cm
->cd
[co
].nchrs
== 1) /* optimization */
393 sco
= newcolor(cm
); /* must create subcolor */
394 if (sco
== COLORLESS
)
399 cm
->cd
[co
].sub
= sco
;
400 cm
->cd
[sco
].sub
= sco
; /* open subcolor points to self */
402 assert(sco
!= NOSUB
);
408 * subrange - allocate new subcolors to this range of chrs, fill in arcs
411 subrange(struct vars
* v
,
422 /* first, align "from" on a tree-block boundary */
424 i
= (int) (((uf
+ BYTTAB
- 1) & (uchr
) ~BYTMASK
) - uf
);
425 for (; from
<= to
&& i
> 0; i
--, from
++)
426 newarc(v
->nfa
, PLAIN
, subcolor(v
->cm
, from
), lp
, rp
);
427 if (from
> to
) /* didn't reach a boundary */
430 /* deal with whole blocks */
431 for (; to
- from
>= BYTTAB
; from
+= BYTTAB
)
432 subblock(v
, from
, lp
, rp
);
434 /* clean up any remaining partial table */
435 for (; from
<= to
; from
++)
436 newarc(v
->nfa
, PLAIN
, subcolor(v
->cm
, from
), lp
, rp
);
440 * subblock - allocate new subcolors for one tree block of chrs, fill in arcs
443 subblock(struct vars
* v
,
444 chr start
, /* first of BYTTAB chrs */
449 struct colormap
*cm
= v
->cm
;
463 assert((uc
% BYTTAB
) == 0);
465 /* find its color block, making new pointer blocks as needed */
468 for (level
= 0, shift
= BYTBITS
* (NBYTS
- 1); shift
> 0;
469 level
++, shift
-= BYTBITS
)
471 b
= (uc
>> shift
) & BYTMASK
;
475 fillt
= &cm
->tree
[level
+ 1];
476 if (t
== fillt
&& shift
> BYTBITS
)
477 { /* need new ptr block */
478 t
= (union tree
*) MALLOC(sizeof(struct ptrs
));
484 memcpy(VS(t
->tptr
), VS(fillt
->tptr
),
485 BYTTAB
* sizeof(union tree
*));
490 /* special cases: fill block or solid block */
492 cb
= cm
->cd
[co
].block
;
493 if (t
== fillt
|| t
== cb
)
495 /* either way, we want a subcolor solid block */
496 sco
= newsub(cm
, co
);
497 t
= cm
->cd
[sco
].block
;
499 { /* must set it up */
500 t
= (union tree
*) MALLOC(sizeof(struct colors
));
506 for (i
= 0; i
< BYTTAB
; i
++)
508 cm
->cd
[sco
].block
= t
;
510 /* find loop must have run at least once */
512 newarc(v
->nfa
, PLAIN
, sco
, lp
, rp
);
513 cm
->cd
[co
].nchrs
-= BYTTAB
;
514 cm
->cd
[sco
].nchrs
+= BYTTAB
;
518 /* general case, a mixed block to be altered */
523 sco
= newsub(cm
, co
);
524 newarc(v
->nfa
, PLAIN
, sco
, lp
, rp
);
528 t
->tcolor
[i
++] = sco
;
529 } while (i
< BYTTAB
&& t
->tcolor
[i
] == co
);
531 cm
->cd
[co
].nchrs
-= ndone
;
532 cm
->cd
[sco
].nchrs
+= ndone
;
537 * okcolors - promote subcolors to full colors
540 okcolors(struct nfa
* nfa
,
541 struct colormap
* cm
)
543 struct colordesc
*cd
;
544 struct colordesc
*end
= CDEND(cm
);
545 struct colordesc
*scd
;
550 for (cd
= cm
->cd
, co
= 0; cd
< end
; cd
++, co
++)
553 if (UNUSEDCOLOR(cd
) || sco
== NOSUB
)
555 /* has no subcolor, no further action */
559 /* is subcolor, let parent deal with it */
561 else if (cd
->nchrs
== 0)
563 /* parent empty, its arcs change color to subcolor */
566 assert(scd
->nchrs
> 0);
567 assert(scd
->sub
== sco
);
569 while ((a
= cd
->arcs
) != NULL
)
572 /* uncolorchain(cm, a); */
573 cd
->arcs
= a
->colorchain
;
575 /* colorchain(cm, a); */
576 a
->colorchain
= scd
->arcs
;
583 /* parent's arcs must gain parallel subcolor arcs */
586 assert(scd
->nchrs
> 0);
587 assert(scd
->sub
== sco
);
589 for (a
= cd
->arcs
; a
!= NULL
; a
= a
->colorchain
)
592 newarc(nfa
, a
->type
, sco
, a
->from
, a
->to
);
599 * colorchain - add this arc to the color chain of its color
602 colorchain(struct colormap
* cm
,
605 struct colordesc
*cd
= &cm
->cd
[a
->co
];
607 a
->colorchain
= cd
->arcs
;
612 * uncolorchain - delete this arc from the color chain of its color
615 uncolorchain(struct colormap
* cm
,
618 struct colordesc
*cd
= &cm
->cd
[a
->co
];
622 if (aa
== a
) /* easy case */
623 cd
->arcs
= a
->colorchain
;
626 for (; aa
!= NULL
&& aa
->colorchain
!= a
; aa
= aa
->colorchain
)
629 aa
->colorchain
= a
->colorchain
;
631 a
->colorchain
= NULL
; /* paranoia */
635 * singleton - is this character in its own color?
637 static int /* predicate */
638 singleton(struct colormap
* cm
,
641 color co
; /* color of c */
643 co
= GETCOLOR(cm
, c
);
644 if (cm
->cd
[co
].nchrs
== 1 && cm
->cd
[co
].sub
== NOSUB
)
650 * rainbow - add arcs of all full colors (but one) between specified states
653 rainbow(struct nfa
* nfa
,
654 struct colormap
* cm
,
656 pcolor but
, /* COLORLESS if no exceptions */
660 struct colordesc
*cd
;
661 struct colordesc
*end
= CDEND(cm
);
664 for (cd
= cm
->cd
, co
= 0; cd
< end
&& !CISERR(); cd
++, co
++)
665 if (!UNUSEDCOLOR(cd
) && cd
->sub
!= co
&& co
!= but
&&
666 !(cd
->flags
& PSEUDO
))
667 newarc(nfa
, type
, co
, from
, to
);
671 * colorcomplement - add arcs of complementary colors
673 * The calling sequence ought to be reconciled with cloneouts().
676 colorcomplement(struct nfa
* nfa
,
677 struct colormap
* cm
,
679 struct state
* of
, /* complements of this guy's PLAIN
684 struct colordesc
*cd
;
685 struct colordesc
*end
= CDEND(cm
);
689 for (cd
= cm
->cd
, co
= 0; cd
< end
&& !CISERR(); cd
++, co
++)
690 if (!UNUSEDCOLOR(cd
) && !(cd
->flags
& PSEUDO
))
691 if (findarc(of
, PLAIN
, co
) == NULL
)
692 newarc(nfa
, type
, co
, from
, to
);
699 * dumpcolors - debugging output
702 dumpcolors(struct colormap
* cm
,
705 struct colordesc
*cd
;
706 struct colordesc
*end
;
711 fprintf(f
, "max %ld\n", (long) cm
->max
);
713 fillcheck(cm
, cm
->tree
, 0, f
);
715 for (cd
= cm
->cd
+ 1, co
= 1; cd
< end
; cd
++, co
++) /* skip 0 */
716 if (!UNUSEDCOLOR(cd
))
718 assert(cd
->nchrs
> 0);
719 has
= (cd
->block
!= NULL
) ? "#" : "";
720 if (cd
->flags
& PSEUDO
)
721 fprintf(f
, "#%2ld%s(ps): ", (long) co
, has
);
723 fprintf(f
, "#%2ld%s(%2d): ", (long) co
,
725 /* it's hard to do this more efficiently */
726 for (c
= CHR_MIN
; c
< CHR_MAX
; c
++)
727 if (GETCOLOR(cm
, c
) == co
)
729 assert(c
== CHR_MAX
);
730 if (GETCOLOR(cm
, c
) == co
)
737 * fillcheck - check proper filling of a tree
740 fillcheck(struct colormap
* cm
,
742 int level
, /* level number (top == 0) of this block */
747 union tree
*fillt
= &cm
->tree
[level
+ 1];
749 assert(level
< NBYTS
- 1); /* this level has pointers */
750 for (i
= BYTTAB
- 1; i
>= 0; i
--)
754 fprintf(f
, "NULL found in filled tree!\n");
758 else if (level
< NBYTS
- 2) /* more pointer blocks below */
759 fillcheck(cm
, t
, level
+ 1, f
);
764 * dumpchr - print a chr
766 * Kind of char-centric but works well enough for debug use.
774 else if (c
> ' ' && c
<= '~')
777 fprintf(f
, "\\u%04lx", (long) c
);
780 #endif /* REG_DEBUG */