regc_color.c 16.3 KB
Newer Older
1 2 3 4
/*
 * colorings of characters
 * This file is #included by regcomp.c.
 *
B
Bruce Momjian 已提交
5 6
 * Copyright (c) 1998, 1999 Henry Spencer.	All rights reserved.
 *
7 8 9
 * Development of this software was funded, in part, by Cray Research Inc.,
 * UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
 * Corporation, none of whom are responsible for the results.  The author
B
Bruce Momjian 已提交
10 11
 * thanks all of them.
 *
12 13 14 15
 * Redistribution and use in source and binary forms -- with or without
 * modification -- are permitted for any purpose, provided that
 * redistributions in source form retain this entire copyright notice and
 * indicate the origin and nature of any modifications.
B
Bruce Momjian 已提交
16
 *
17 18
 * I'd appreciate being given credit for this package in the documentation
 * of software which uses it, but that is not a requirement.
B
Bruce Momjian 已提交
19
 *
20 21 22 23 24 25 26 27 28 29 30
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
 * HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
31
 * $PostgreSQL: pgsql/src/backend/regex/regc_color.c,v 1.9 2008/02/14 17:33:37 tgl Exp $
32 33 34 35 36 37 38 39
 *
 *
 * Note that there are some incestuous relationships between this code and
 * NFA arc maintenance, which perhaps ought to be cleaned up sometime.
 */



B
Bruce Momjian 已提交
40 41
#define CISERR()	VISERR(cm->v)
#define CERR(e)		VERR(cm->v, (e))
42 43 44 45 46 47 48



/*
 * initcm - set up new colormap
 */
static void
B
Bruce Momjian 已提交
49 50
initcm(struct vars * v,
	   struct colormap * cm)
51
{
B
Bruce Momjian 已提交
52 53
	int			i;
	int			j;
54 55 56 57 58 59 60 61 62 63 64 65
	union tree *t;
	union tree *nextt;
	struct colordesc *cd;

	cm->magic = CMMAGIC;
	cm->v = v;

	cm->ncds = NINLINECDS;
	cm->cd = cm->cdspace;
	cm->max = 0;
	cm->free = 0;

B
Bruce Momjian 已提交
66
	cd = cm->cd;				/* cm->cd[WHITE] */
67 68 69 70 71 72
	cd->sub = NOSUB;
	cd->arcs = NULL;
	cd->flags = 0;
	cd->nchrs = CHR_MAX - CHR_MIN + 1;

	/* upper levels of tree */
B
Bruce Momjian 已提交
73 74
	for (t = &cm->tree[0], j = NBYTS - 1; j > 0; t = nextt, j--)
	{
75
		nextt = t + 1;
B
Bruce Momjian 已提交
76
		for (i = BYTTAB - 1; i >= 0; i--)
77 78 79
			t->tptr[i] = nextt;
	}
	/* bottom level is solid white */
B
Bruce Momjian 已提交
80 81
	t = &cm->tree[NBYTS - 1];
	for (i = BYTTAB - 1; i >= 0; i--)
82 83 84 85 86 87 88 89
		t->tcolor[i] = WHITE;
	cd->block = t;
}

/*
 * freecm - free dynamically-allocated things in a colormap
 */
static void
B
Bruce Momjian 已提交
90
freecm(struct colormap * cm)
91
{
B
Bruce Momjian 已提交
92
	size_t		i;
93 94 95 96 97 98
	union tree *cb;

	cm->magic = 0;
	if (NBYTS > 1)
		cmtreefree(cm, cm->tree, 0);
	for (i = 1; i <= cm->max; i++)		/* skip WHITE */
B
Bruce Momjian 已提交
99 100
		if (!UNUSEDCOLOR(&cm->cd[i]))
		{
101 102 103 104 105 106 107 108 109 110 111 112
			cb = cm->cd[i].block;
			if (cb != NULL)
				FREE(cb);
		}
	if (cm->cd != cm->cdspace)
		FREE(cm->cd);
}

/*
 * cmtreefree - free a non-terminal part of a colormap tree
 */
static void
B
Bruce Momjian 已提交
113 114
cmtreefree(struct colormap * cm,
		   union tree * tree,
115 116
		   int level)			/* level number (top == 0) of this block */
{
B
Bruce Momjian 已提交
117
	int			i;
118
	union tree *t;
B
Bruce Momjian 已提交
119
	union tree *fillt = &cm->tree[level + 1];
120 121
	union tree *cb;

B
Bruce Momjian 已提交
122 123 124
	assert(level < NBYTS - 1);	/* this level has pointers */
	for (i = BYTTAB - 1; i >= 0; i--)
	{
125 126
		t = tree->tptr[i];
		assert(t != NULL);
B
Bruce Momjian 已提交
127 128 129 130 131
		if (t != fillt)
		{
			if (level < NBYTS - 2)
			{					/* more pointer blocks below */
				cmtreefree(cm, t, level + 1);
132
				FREE(t);
B
Bruce Momjian 已提交
133 134 135
			}
			else
			{					/* color block below */
136 137 138 139 140 141 142 143 144 145 146
				cb = cm->cd[t->tcolor[0]].block;
				if (t != cb)	/* not a solid block */
					FREE(t);
			}
		}
	}
}

/*
 * setcolor - set the color of a character in a colormap
 */
147
static color					/* previous color */
B
Bruce Momjian 已提交
148
setcolor(struct colormap * cm,
149 150 151
		 chr c,
		 pcolor co)
{
B
Bruce Momjian 已提交
152 153 154 155 156
	uchr		uc = c;
	int			shift;
	int			level;
	int			b;
	int			bottom;
157 158 159 160 161
	union tree *t;
	union tree *newt;
	union tree *fillt;
	union tree *lastt;
	union tree *cb;
B
Bruce Momjian 已提交
162
	color		prev;
163 164 165 166 167 168 169

	assert(cm->magic == CMMAGIC);
	if (CISERR() || co == COLORLESS)
		return COLORLESS;

	t = cm->tree;
	for (level = 0, shift = BYTBITS * (NBYTS - 1); shift > 0;
B
Bruce Momjian 已提交
170 171
		 level++, shift -= BYTBITS)
	{
172 173 174 175
		b = (uc >> shift) & BYTMASK;
		lastt = t;
		t = lastt->tptr[b];
		assert(t != NULL);
B
Bruce Momjian 已提交
176
		fillt = &cm->tree[level + 1];
177 178
		bottom = (shift <= BYTBITS) ? 1 : 0;
		cb = (bottom) ? cm->cd[t->tcolor[0]].block : fillt;
B
Bruce Momjian 已提交
179 180 181
		if (t == fillt || t == cb)
		{						/* must allocate a new block */
			newt = (union tree *) MALLOC((bottom) ?
B
Bruce Momjian 已提交
182
								sizeof(struct colors) : sizeof(struct ptrs));
B
Bruce Momjian 已提交
183 184
			if (newt == NULL)
			{
185 186 187 188 189
				CERR(REG_ESPACE);
				return COLORLESS;
			}
			if (bottom)
				memcpy(VS(newt->tcolor), VS(t->tcolor),
B
Bruce Momjian 已提交
190
					   BYTTAB * sizeof(color));
191 192
			else
				memcpy(VS(newt->tptr), VS(t->tptr),
B
Bruce Momjian 已提交
193
					   BYTTAB * sizeof(union tree *));
194 195 196 197 198 199 200
			t = newt;
			lastt->tptr[b] = t;
		}
	}

	b = uc & BYTMASK;
	prev = t->tcolor[b];
B
Bruce Momjian 已提交
201
	t->tcolor[b] = (color) co;
202 203 204 205 206 207 208
	return prev;
}

/*
 * maxcolor - report largest color number in use
 */
static color
B
Bruce Momjian 已提交
209
maxcolor(struct colormap * cm)
210 211 212 213
{
	if (CISERR())
		return COLORLESS;

B
Bruce Momjian 已提交
214
	return (color) cm->max;
215 216 217 218
}

/*
 * newcolor - find a new color (must be subject of setcolor at once)
B
Bruce Momjian 已提交
219
 * Beware:	may relocate the colordescs.
220
 */
221
static color					/* COLORLESS for error */
B
Bruce Momjian 已提交
222
newcolor(struct colormap * cm)
223 224
{
	struct colordesc *cd;
B
Bruce Momjian 已提交
225
	size_t		n;
226 227 228 229

	if (CISERR())
		return COLORLESS;

B
Bruce Momjian 已提交
230 231
	if (cm->free != 0)
	{
232
		assert(cm->free > 0);
B
Bruce Momjian 已提交
233
		assert((size_t) cm->free < cm->ncds);
234 235 236 237
		cd = &cm->cd[cm->free];
		assert(UNUSEDCOLOR(cd));
		assert(cd->arcs == NULL);
		cm->free = cd->sub;
B
Bruce Momjian 已提交
238 239 240
	}
	else if (cm->max < cm->ncds - 1)
	{
241 242
		cm->max++;
		cd = &cm->cd[cm->max];
B
Bruce Momjian 已提交
243 244 245
	}
	else
	{
246
		/* oops, must allocate more */
247 248
		struct colordesc *newCd;

249
		n = cm->ncds * 2;
B
Bruce Momjian 已提交
250 251
		if (cm->cd == cm->cdspace)
		{
252 253 254
			newCd = (struct colordesc *) MALLOC(n * sizeof(struct colordesc));
			if (newCd != NULL)
				memcpy(VS(newCd), VS(cm->cdspace), cm->ncds *
B
Bruce Momjian 已提交
255 256 257
					   sizeof(struct colordesc));
		}
		else
258 259 260
			newCd = (struct colordesc *)
				REALLOC(cm->cd, n * sizeof(struct colordesc));
		if (newCd == NULL)
B
Bruce Momjian 已提交
261
		{
262 263 264
			CERR(REG_ESPACE);
			return COLORLESS;
		}
265
		cm->cd = newCd;
266 267 268 269 270 271 272 273 274 275 276 277
		cm->ncds = n;
		assert(cm->max < cm->ncds - 1);
		cm->max++;
		cd = &cm->cd[cm->max];
	}

	cd->nchrs = 0;
	cd->sub = NOSUB;
	cd->arcs = NULL;
	cd->flags = 0;
	cd->block = NULL;

B
Bruce Momjian 已提交
278
	return (color) (cd - cm->cd);
279 280 281 282 283 284
}

/*
 * freecolor - free a color (must have no arcs or subcolor)
 */
static void
B
Bruce Momjian 已提交
285
freecolor(struct colormap * cm,
286 287 288
		  pcolor co)
{
	struct colordesc *cd = &cm->cd[co];
B
Bruce Momjian 已提交
289 290
	color		pco,
				nco;			/* for freelist scan */
291 292 293 294 295 296 297 298 299

	assert(co >= 0);
	if (co == WHITE)
		return;

	assert(cd->arcs == NULL);
	assert(cd->sub == NOSUB);
	assert(cd->nchrs == 0);
	cd->flags = FREECOL;
B
Bruce Momjian 已提交
300 301
	if (cd->block != NULL)
	{
302
		FREE(cd->block);
B
Bruce Momjian 已提交
303
		cd->block = NULL;		/* just paranoia */
304 305
	}

B
Bruce Momjian 已提交
306 307
	if ((size_t) co == cm->max)
	{
308 309 310
		while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max]))
			cm->max--;
		assert(cm->free >= 0);
B
Bruce Momjian 已提交
311
		while ((size_t) cm->free > cm->max)
312
			cm->free = cm->cd[cm->free].sub;
B
Bruce Momjian 已提交
313 314
		if (cm->free > 0)
		{
315 316 317 318
			assert(cm->free < cm->max);
			pco = cm->free;
			nco = cm->cd[pco].sub;
			while (nco > 0)
B
Bruce Momjian 已提交
319 320
				if ((size_t) nco > cm->max)
				{
321 322 323
					/* take this one out of freelist */
					nco = cm->cd[nco].sub;
					cm->cd[pco].sub = nco;
B
Bruce Momjian 已提交
324 325 326
				}
				else
				{
327 328 329 330 331
					assert(nco < cm->max);
					pco = nco;
					nco = cm->cd[pco].sub;
				}
		}
B
Bruce Momjian 已提交
332 333 334
	}
	else
	{
335
		cd->sub = cm->free;
B
Bruce Momjian 已提交
336
		cm->free = (color) (cd - cm->cd);
337 338 339 340 341 342 343
	}
}

/*
 * pseudocolor - allocate a false color, to be managed by other means
 */
static color
B
Bruce Momjian 已提交
344
pseudocolor(struct colormap * cm)
345
{
B
Bruce Momjian 已提交
346
	color		co;
347 348 349 350 351 352 353 354 355 356 357 358 359

	co = newcolor(cm);
	if (CISERR())
		return COLORLESS;
	cm->cd[co].nchrs = 1;
	cm->cd[co].flags = PSEUDO;
	return co;
}

/*
 * subcolor - allocate a new subcolor (if necessary) to this chr
 */
static color
B
Bruce Momjian 已提交
360
subcolor(struct colormap * cm, chr c)
361
{
B
Bruce Momjian 已提交
362 363
	color		co;				/* current color of c */
	color		sco;			/* new subcolor */
364 365 366 367 368 369 370

	co = GETCOLOR(cm, c);
	sco = newsub(cm, co);
	if (CISERR())
		return COLORLESS;
	assert(sco != COLORLESS);

B
Bruce Momjian 已提交
371 372
	if (co == sco)				/* already in an open subcolor */
		return co;				/* rest is redundant */
373 374 375 376 377 378 379 380 381 382
	cm->cd[co].nchrs--;
	cm->cd[sco].nchrs++;
	setcolor(cm, c, sco);
	return sco;
}

/*
 * newsub - allocate a new subcolor (if necessary) for a color
 */
static color
B
Bruce Momjian 已提交
383
newsub(struct colormap * cm,
384 385
	   pcolor co)
{
B
Bruce Momjian 已提交
386
	color		sco;			/* new subcolor */
387 388

	sco = cm->cd[co].sub;
B
Bruce Momjian 已提交
389 390 391
	if (sco == NOSUB)
	{							/* color has no open subcolor */
		if (cm->cd[co].nchrs == 1)		/* optimization */
392
			return co;
B
Bruce Momjian 已提交
393 394 395
		sco = newcolor(cm);		/* must create subcolor */
		if (sco == COLORLESS)
		{
396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
			assert(CISERR());
			return COLORLESS;
		}
		cm->cd[co].sub = sco;
		cm->cd[sco].sub = sco;	/* open subcolor points to self */
	}
	assert(sco != NOSUB);

	return sco;
}

/*
 * subrange - allocate new subcolors to this range of chrs, fill in arcs
 */
static void
B
Bruce Momjian 已提交
411
subrange(struct vars * v,
412 413
		 chr from,
		 chr to,
B
Bruce Momjian 已提交
414 415
		 struct state * lp,
		 struct state * rp)
416
{
B
Bruce Momjian 已提交
417 418
	uchr		uf;
	int			i;
419 420 421 422

	assert(from <= to);

	/* first, align "from" on a tree-block boundary */
B
Bruce Momjian 已提交
423
	uf = (uchr) from;
424
	i = (int) (((uf + BYTTAB - 1) & (uchr) ~BYTMASK) - uf);
425 426
	for (; from <= to && i > 0; i--, from++)
		newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
B
Bruce Momjian 已提交
427
	if (from > to)				/* didn't reach a boundary */
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
		return;

	/* deal with whole blocks */
	for (; to - from >= BYTTAB; from += BYTTAB)
		subblock(v, from, lp, rp);

	/* clean up any remaining partial table */
	for (; from <= to; from++)
		newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
}

/*
 * subblock - allocate new subcolors for one tree block of chrs, fill in arcs
 */
static void
B
Bruce Momjian 已提交
443
subblock(struct vars * v,
444
		 chr start,				/* first of BYTTAB chrs */
B
Bruce Momjian 已提交
445 446
		 struct state * lp,
		 struct state * rp)
447
{
B
Bruce Momjian 已提交
448
	uchr		uc = start;
449
	struct colormap *cm = v->cm;
B
Bruce Momjian 已提交
450 451 452 453
	int			shift;
	int			level;
	int			i;
	int			b;
454 455 456 457
	union tree *t;
	union tree *cb;
	union tree *fillt;
	union tree *lastt;
B
Bruce Momjian 已提交
458 459 460 461
	int			previ;
	int			ndone;
	color		co;
	color		sco;
462 463 464 465 466 467 468

	assert((uc % BYTTAB) == 0);

	/* find its color block, making new pointer blocks as needed */
	t = cm->tree;
	fillt = NULL;
	for (level = 0, shift = BYTBITS * (NBYTS - 1); shift > 0;
B
Bruce Momjian 已提交
469 470
		 level++, shift -= BYTBITS)
	{
471 472 473 474
		b = (uc >> shift) & BYTMASK;
		lastt = t;
		t = lastt->tptr[b];
		assert(t != NULL);
B
Bruce Momjian 已提交
475 476 477 478 479 480
		fillt = &cm->tree[level + 1];
		if (t == fillt && shift > BYTBITS)
		{						/* need new ptr block */
			t = (union tree *) MALLOC(sizeof(struct ptrs));
			if (t == NULL)
			{
481 482 483 484
				CERR(REG_ESPACE);
				return;
			}
			memcpy(VS(t->tptr), VS(fillt->tptr),
B
Bruce Momjian 已提交
485
				   BYTTAB * sizeof(union tree *));
486 487 488 489 490 491 492
			lastt->tptr[b] = t;
		}
	}

	/* special cases:  fill block or solid block */
	co = t->tcolor[0];
	cb = cm->cd[co].block;
B
Bruce Momjian 已提交
493 494
	if (t == fillt || t == cb)
	{
495 496 497
		/* either way, we want a subcolor solid block */
		sco = newsub(cm, co);
		t = cm->cd[sco].block;
B
Bruce Momjian 已提交
498 499 500 501 502
		if (t == NULL)
		{						/* must set it up */
			t = (union tree *) MALLOC(sizeof(struct colors));
			if (t == NULL)
			{
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
				CERR(REG_ESPACE);
				return;
			}
			for (i = 0; i < BYTTAB; i++)
				t->tcolor[i] = sco;
			cm->cd[sco].block = t;
		}
		/* find loop must have run at least once */
		lastt->tptr[b] = t;
		newarc(v->nfa, PLAIN, sco, lp, rp);
		cm->cd[co].nchrs -= BYTTAB;
		cm->cd[sco].nchrs += BYTTAB;
		return;
	}

	/* general case, a mixed block to be altered */
	i = 0;
B
Bruce Momjian 已提交
520 521
	while (i < BYTTAB)
	{
522 523 524 525
		co = t->tcolor[i];
		sco = newsub(cm, co);
		newarc(v->nfa, PLAIN, sco, lp, rp);
		previ = i;
B
Bruce Momjian 已提交
526 527
		do
		{
528 529 530 531 532 533 534 535 536 537 538 539
			t->tcolor[i++] = sco;
		} while (i < BYTTAB && t->tcolor[i] == co);
		ndone = i - previ;
		cm->cd[co].nchrs -= ndone;
		cm->cd[sco].nchrs += ndone;
	}
}

/*
 * okcolors - promote subcolors to full colors
 */
static void
B
Bruce Momjian 已提交
540 541
okcolors(struct nfa * nfa,
		 struct colormap * cm)
542 543 544 545 546
{
	struct colordesc *cd;
	struct colordesc *end = CDEND(cm);
	struct colordesc *scd;
	struct arc *a;
B
Bruce Momjian 已提交
547 548
	color		co;
	color		sco;
549

B
Bruce Momjian 已提交
550 551
	for (cd = cm->cd, co = 0; cd < end; cd++, co++)
	{
552
		sco = cd->sub;
B
Bruce Momjian 已提交
553 554
		if (UNUSEDCOLOR(cd) || sco == NOSUB)
		{
555
			/* has no subcolor, no further action */
B
Bruce Momjian 已提交
556 557 558
		}
		else if (sco == co)
		{
559
			/* is subcolor, let parent deal with it */
B
Bruce Momjian 已提交
560 561 562
		}
		else if (cd->nchrs == 0)
		{
563 564 565 566 567 568
			/* parent empty, its arcs change color to subcolor */
			cd->sub = NOSUB;
			scd = &cm->cd[sco];
			assert(scd->nchrs > 0);
			assert(scd->sub == sco);
			scd->sub = NOSUB;
B
Bruce Momjian 已提交
569 570
			while ((a = cd->arcs) != NULL)
			{
571
				assert(a->co == co);
572
				uncolorchain(cm, a);
573
				a->co = sco;
574
				colorchain(cm, a);
575 576
			}
			freecolor(cm, co);
B
Bruce Momjian 已提交
577 578 579
		}
		else
		{
580 581 582 583 584 585
			/* parent's arcs must gain parallel subcolor arcs */
			cd->sub = NOSUB;
			scd = &cm->cd[sco];
			assert(scd->nchrs > 0);
			assert(scd->sub == sco);
			scd->sub = NOSUB;
B
Bruce Momjian 已提交
586 587
			for (a = cd->arcs; a != NULL; a = a->colorchain)
			{
588 589 590 591 592 593 594 595 596 597 598
				assert(a->co == co);
				newarc(nfa, a->type, sco, a->from, a->to);
			}
		}
	}
}

/*
 * colorchain - add this arc to the color chain of its color
 */
static void
B
Bruce Momjian 已提交
599 600
colorchain(struct colormap * cm,
		   struct arc * a)
601 602 603
{
	struct colordesc *cd = &cm->cd[a->co];

604 605
	if (cd->arcs != NULL)
		cd->arcs->colorchainRev = a;
606
	a->colorchain = cd->arcs;
607
	a->colorchainRev = NULL;
608 609 610 611 612 613 614
	cd->arcs = a;
}

/*
 * uncolorchain - delete this arc from the color chain of its color
 */
static void
B
Bruce Momjian 已提交
615 616
uncolorchain(struct colormap * cm,
			 struct arc * a)
617 618
{
	struct colordesc *cd = &cm->cd[a->co];
619
	struct arc *aa = a->colorchainRev;
620

621 622 623
	if (aa == NULL)
	{
		assert(cd->arcs == a);
624
		cd->arcs = a->colorchain;
625
	}
B
Bruce Momjian 已提交
626 627
	else
	{
628
		assert(aa->colorchain == a);
629 630
		aa->colorchain = a->colorchain;
	}
631 632
	if (a->colorchain != NULL)
		a->colorchain->colorchainRev = aa;
B
Bruce Momjian 已提交
633
	a->colorchain = NULL;		/* paranoia */
634
	a->colorchainRev = NULL;
635 636 637 638 639 640
}

/*
 * rainbow - add arcs of all full colors (but one) between specified states
 */
static void
B
Bruce Momjian 已提交
641 642
rainbow(struct nfa * nfa,
		struct colormap * cm,
643 644
		int type,
		pcolor but,				/* COLORLESS if no exceptions */
B
Bruce Momjian 已提交
645 646
		struct state * from,
		struct state * to)
647 648 649
{
	struct colordesc *cd;
	struct colordesc *end = CDEND(cm);
B
Bruce Momjian 已提交
650
	color		co;
651 652 653

	for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
		if (!UNUSEDCOLOR(cd) && cd->sub != co && co != but &&
B
Bruce Momjian 已提交
654
			!(cd->flags & PSEUDO))
655 656 657 658 659 660 661 662 663
			newarc(nfa, type, co, from, to);
}

/*
 * colorcomplement - add arcs of complementary colors
 *
 * The calling sequence ought to be reconciled with cloneouts().
 */
static void
B
Bruce Momjian 已提交
664 665
colorcomplement(struct nfa * nfa,
				struct colormap * cm,
666
				int type,
B
Bruce Momjian 已提交
667 668 669 670
				struct state * of,		/* complements of this guy's PLAIN
										 * outarcs */
				struct state * from,
				struct state * to)
671 672 673
{
	struct colordesc *cd;
	struct colordesc *end = CDEND(cm);
B
Bruce Momjian 已提交
674
	color		co;
675 676 677

	assert(of != from);
	for (cd = cm->cd, co = 0; cd < end && !CISERR(); cd++, co++)
B
Bruce Momjian 已提交
678
		if (!UNUSEDCOLOR(cd) && !(cd->flags & PSEUDO))
679 680 681 682 683 684 685 686 687 688 689
			if (findarc(of, PLAIN, co) == NULL)
				newarc(nfa, type, co, from, to);
}


#ifdef REG_DEBUG

/*
 * dumpcolors - debugging output
 */
static void
B
Bruce Momjian 已提交
690
dumpcolors(struct colormap * cm,
691 692 693 694
		   FILE *f)
{
	struct colordesc *cd;
	struct colordesc *end;
B
Bruce Momjian 已提交
695 696 697
	color		co;
	chr			c;
	char	   *has;
698

B
Bruce Momjian 已提交
699
	fprintf(f, "max %ld\n", (long) cm->max);
700 701 702
	if (NBYTS > 1)
		fillcheck(cm, cm->tree, 0, f);
	end = CDEND(cm);
B
Bruce Momjian 已提交
703 704 705
	for (cd = cm->cd + 1, co = 1; cd < end; cd++, co++) /* skip 0 */
		if (!UNUSEDCOLOR(cd))
		{
706 707
			assert(cd->nchrs > 0);
			has = (cd->block != NULL) ? "#" : "";
B
Bruce Momjian 已提交
708 709
			if (cd->flags & PSEUDO)
				fprintf(f, "#%2ld%s(ps): ", (long) co, has);
710
			else
B
Bruce Momjian 已提交
711 712
				fprintf(f, "#%2ld%s(%2d): ", (long) co,
						has, cd->nchrs);
B
Bruce Momjian 已提交
713

714 715 716 717
			/*
			 * Unfortunately, it's hard to do this next bit more efficiently.
			 *
			 * Spencer's original coding has the loop iterating from CHR_MIN
B
Bruce Momjian 已提交
718 719 720
			 * to CHR_MAX, but that's utterly unusable for 32-bit chr. For
			 * debugging purposes it seems fine to print only chr codes up to
			 * 1000 or so.
721 722
			 */
			for (c = CHR_MIN; c < 1000; c++)
723 724 725 726 727 728 729 730 731 732
				if (GETCOLOR(cm, c) == co)
					dumpchr(c, f);
			fprintf(f, "\n");
		}
}

/*
 * fillcheck - check proper filling of a tree
 */
static void
B
Bruce Momjian 已提交
733 734
fillcheck(struct colormap * cm,
		  union tree * tree,
735 736 737
		  int level,			/* level number (top == 0) of this block */
		  FILE *f)
{
B
Bruce Momjian 已提交
738
	int			i;
739
	union tree *t;
B
Bruce Momjian 已提交
740
	union tree *fillt = &cm->tree[level + 1];
741

B
Bruce Momjian 已提交
742 743 744
	assert(level < NBYTS - 1);	/* this level has pointers */
	for (i = BYTTAB - 1; i >= 0; i--)
	{
745 746 747 748
		t = tree->tptr[i];
		if (t == NULL)
			fprintf(f, "NULL found in filled tree!\n");
		else if (t == fillt)
B
Bruce Momjian 已提交
749 750 751 752
		{
		}
		else if (level < NBYTS - 2)		/* more pointer blocks below */
			fillcheck(cm, t, level + 1, f);
753 754 755 756 757 758 759 760 761 762 763 764 765 766 767
	}
}

/*
 * dumpchr - print a chr
 *
 * Kind of char-centric but works well enough for debug use.
 */
static void
dumpchr(chr c,
		FILE *f)
{
	if (c == '\\')
		fprintf(f, "\\\\");
	else if (c > ' ' && c <= '~')
B
Bruce Momjian 已提交
768
		putc((char) c, f);
769
	else
B
Bruce Momjian 已提交
770
		fprintf(f, "\\u%04lx", (long) c);
771 772
}

B
Bruce Momjian 已提交
773
#endif   /* REG_DEBUG */