12258Scsgr/* ecs - equivalence class routines */
22258Scsgr
32258Scsgr/*-
42258Scsgr * Copyright (c) 1990 The Regents of the University of California.
52258Scsgr * All rights reserved.
62258Scsgr *
72258Scsgr * This code is derived from software contributed to Berkeley by
82258Scsgr * Vern Paxson.
916519Snate *
102258Scsgr * The United States Government has rights in this work pursuant
112258Scsgr * to contract no. DE-AC03-76SF00098 between the United States
122258Scsgr * Department of Energy and the University of California.
132258Scsgr *
142258Scsgr * Redistribution and use in source and binary forms are permitted provided
152258Scsgr * that: (1) source distributions retain this entire copyright notice and
162258Scsgr * comment, and (2) distributions including binaries display the following
172258Scsgr * acknowledgement:  ``This product includes software developed by the
182258Scsgr * University of California, Berkeley and its contributors'' in the
192258Scsgr * documentation or other materials provided with the distribution and in
202258Scsgr * all advertising materials mentioning features or use of this software.
212258Scsgr * Neither the name of the University nor the names of its contributors may
222258Scsgr * be used to endorse or promote products derived from this software without
232258Scsgr * specific prior written permission.
242258Scsgr * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
252258Scsgr * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
262258Scsgr * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
272258Scsgr */
282258Scsgr
2952555Sobrien/* $Header: /home/daffy/u0/vern/flex/RCS/ecs.c,v 2.9 93/12/07 10:18:20 vern Exp $ */
3099112Sobrien#include <sys/cdefs.h>
3199112Sobrien__FBSDID("$FreeBSD$");
322258Scsgr
332258Scsgr#include "flexdef.h"
342258Scsgr
352258Scsgr/* ccl2ecl - convert character classes to set of equivalence classes */
362258Scsgr
372258Scsgrvoid ccl2ecl()
382258Scsgr	{
392258Scsgr	int i, ich, newlen, cclp, ccls, cclmec;
402258Scsgr
412258Scsgr	for ( i = 1; i <= lastccl; ++i )
422258Scsgr		{
432258Scsgr		/* We loop through each character class, and for each character
442258Scsgr		 * in the class, add the character's equivalence class to the
452258Scsgr		 * new "character" class we are creating.  Thus when we are all
462258Scsgr		 * done, character classes will really consist of collections
472258Scsgr		 * of equivalence classes
482258Scsgr		 */
492258Scsgr
502258Scsgr		newlen = 0;
512258Scsgr		cclp = cclmap[i];
522258Scsgr
532258Scsgr		for ( ccls = 0; ccls < ccllen[i]; ++ccls )
542258Scsgr			{
552258Scsgr			ich = ccltbl[cclp + ccls];
562258Scsgr			cclmec = ecgroup[ich];
572258Scsgr
582258Scsgr			if ( cclmec > 0 )
592258Scsgr				{
602258Scsgr				ccltbl[cclp + newlen] = cclmec;
612258Scsgr				++newlen;
622258Scsgr				}
632258Scsgr			}
642258Scsgr
652258Scsgr		ccllen[i] = newlen;
662258Scsgr		}
672258Scsgr	}
682258Scsgr
692258Scsgr
702258Scsgr/* cre8ecs - associate equivalence class numbers with class members
712258Scsgr *
722258Scsgr * fwd is the forward linked-list of equivalence class members.  bck
732258Scsgr * is the backward linked-list, and num is the number of class members.
742258Scsgr *
752258Scsgr * Returned is the number of classes.
762258Scsgr */
772258Scsgr
782258Scsgrint cre8ecs( fwd, bck, num )
792258Scsgrint fwd[], bck[], num;
802258Scsgr	{
812258Scsgr	int i, j, numcl;
822258Scsgr
832258Scsgr	numcl = 0;
842258Scsgr
852258Scsgr	/* Create equivalence class numbers.  From now on, ABS( bck(x) )
862258Scsgr	 * is the equivalence class number for object x.  If bck(x)
872258Scsgr	 * is positive, then x is the representative of its equivalence
882258Scsgr	 * class.
892258Scsgr	 */
902258Scsgr	for ( i = 1; i <= num; ++i )
912258Scsgr		if ( bck[i] == NIL )
922258Scsgr			{
932258Scsgr			bck[i] = ++numcl;
942258Scsgr			for ( j = fwd[i]; j != NIL; j = fwd[j] )
952258Scsgr				bck[j] = -numcl;
962258Scsgr			}
972258Scsgr
982258Scsgr	return numcl;
992258Scsgr	}
1002258Scsgr
1012258Scsgr
1022258Scsgr/* mkeccl - update equivalence classes based on character class xtions
1032258Scsgr *
1042258Scsgr * synopsis
1052258Scsgr *    Char ccls[];
1062258Scsgr *    int lenccl, fwd[llsiz], bck[llsiz], llsiz, NUL_mapping;
1072258Scsgr *    void mkeccl( Char ccls[], int lenccl, int fwd[llsiz], int bck[llsiz],
1082258Scsgr *			int llsiz, int NUL_mapping );
1092258Scsgr *
1102258Scsgr * ccls contains the elements of the character class, lenccl is the
1112258Scsgr * number of elements in the ccl, fwd is the forward link-list of equivalent
1122258Scsgr * characters, bck is the backward link-list, and llsiz size of the link-list.
1132258Scsgr *
1142258Scsgr * NUL_mapping is the value which NUL (0) should be mapped to.
1152258Scsgr */
1162258Scsgr
1172258Scsgrvoid mkeccl( ccls, lenccl, fwd, bck, llsiz, NUL_mapping )
1182258ScsgrChar ccls[];
1192258Scsgrint lenccl, fwd[], bck[], llsiz, NUL_mapping;
1202258Scsgr	{
1212258Scsgr	int cclp, oldec, newec;
1222258Scsgr	int cclm, i, j;
1232258Scsgr	static unsigned char cclflags[CSIZE];	/* initialized to all '\0' */
1242258Scsgr
1252258Scsgr	/* Note that it doesn't matter whether or not the character class is
1262258Scsgr	 * negated.  The same results will be obtained in either case.
1272258Scsgr	 */
1282258Scsgr
1292258Scsgr	cclp = 0;
1302258Scsgr
1312258Scsgr	while ( cclp < lenccl )
1322258Scsgr		{
1332258Scsgr		cclm = ccls[cclp];
1342258Scsgr
1352258Scsgr		if ( NUL_mapping && cclm == 0 )
1362258Scsgr			cclm = NUL_mapping;
1372258Scsgr
1382258Scsgr		oldec = bck[cclm];
1392258Scsgr		newec = cclm;
1402258Scsgr
1412258Scsgr		j = cclp + 1;
1422258Scsgr
1432258Scsgr		for ( i = fwd[cclm]; i != NIL && i <= llsiz; i = fwd[i] )
1442258Scsgr			{ /* look for the symbol in the character class */
1452258Scsgr			for ( ; j < lenccl; ++j )
1462258Scsgr				{
147179549Sdwmalone				int ccl_char;
1482258Scsgr
1492258Scsgr				if ( NUL_mapping && ccls[j] == 0 )
1502258Scsgr					ccl_char = NUL_mapping;
1512258Scsgr				else
1522258Scsgr					ccl_char = ccls[j];
1532258Scsgr
1542258Scsgr				if ( ccl_char > i )
1552258Scsgr					break;
1562258Scsgr
1572258Scsgr				if ( ccl_char == i && ! cclflags[j] )
1582258Scsgr					{
1592258Scsgr					/* We found an old companion of cclm
1602258Scsgr					 * in the ccl.  Link it into the new
1612258Scsgr					 * equivalence class and flag it as
1622258Scsgr					 * having been processed.
1632258Scsgr					 */
1642258Scsgr
1652258Scsgr					bck[i] = newec;
1662258Scsgr					fwd[newec] = i;
1672258Scsgr					newec = i;
1682258Scsgr					/* Set flag so we don't reprocess. */
1692258Scsgr					cclflags[j] = 1;
1702258Scsgr
1712258Scsgr					/* Get next equivalence class member. */
1722258Scsgr					/* continue 2 */
1732258Scsgr					goto next_pt;
1742258Scsgr					}
1752258Scsgr				}
1762258Scsgr
1772258Scsgr			/* Symbol isn't in character class.  Put it in the old
1782258Scsgr			 * equivalence class.
1792258Scsgr			 */
1802258Scsgr
1812258Scsgr			bck[i] = oldec;
1822258Scsgr
1832258Scsgr			if ( oldec != NIL )
1842258Scsgr				fwd[oldec] = i;
1852258Scsgr
1862258Scsgr			oldec = i;
1872258Scsgr
1882258Scsgr			next_pt: ;
1892258Scsgr			}
1902258Scsgr
1912258Scsgr		if ( bck[cclm] != NIL || oldec != bck[cclm] )
1922258Scsgr			{
1932258Scsgr			bck[cclm] = NIL;
1942258Scsgr			fwd[oldec] = NIL;
1952258Scsgr			}
1962258Scsgr
1972258Scsgr		fwd[newec] = NIL;
1982258Scsgr
1992258Scsgr		/* Find next ccl member to process. */
2002258Scsgr
2012258Scsgr		for ( ++cclp; cclflags[cclp] && cclp < lenccl; ++cclp )
2022258Scsgr			{
2032258Scsgr			/* Reset "doesn't need processing" flag. */
2042258Scsgr			cclflags[cclp] = 0;
2052258Scsgr			}
2062258Scsgr		}
2072258Scsgr	}
2082258Scsgr
2092258Scsgr
2102258Scsgr/* mkechar - create equivalence class for single character */
2112258Scsgr
2122258Scsgrvoid mkechar( tch, fwd, bck )
2132258Scsgrint tch, fwd[], bck[];
2142258Scsgr	{
2152258Scsgr	/* If until now the character has been a proper subset of
2162258Scsgr	 * an equivalence class, break it away to create a new ec
2172258Scsgr	 */
2182258Scsgr
2192258Scsgr	if ( fwd[tch] != NIL )
2202258Scsgr		bck[fwd[tch]] = bck[tch];
2212258Scsgr
2222258Scsgr	if ( bck[tch] != NIL )
2232258Scsgr		fwd[bck[tch]] = fwd[tch];
2242258Scsgr
2252258Scsgr	fwd[tch] = NIL;
2262258Scsgr	bck[tch] = NIL;
2272258Scsgr	}
228