xref: /dflybsd-src/contrib/flex/src/ecs.c (revision 388e4ddaf1c230f115961bdb4bad6a8d3e017c93)
1*d9805213SSascha Wildner /* ecs - equivalence class routines */
2*d9805213SSascha Wildner 
3*d9805213SSascha Wildner /*  Copyright (c) 1990 The Regents of the University of California. */
4*d9805213SSascha Wildner /*  All rights reserved. */
5*d9805213SSascha Wildner 
6*d9805213SSascha Wildner /*  This code is derived from software contributed to Berkeley by */
7*d9805213SSascha Wildner /*  Vern Paxson. */
8*d9805213SSascha Wildner 
9*d9805213SSascha Wildner /*  The United States Government has rights in this work pursuant */
10*d9805213SSascha Wildner /*  to contract no. DE-AC03-76SF00098 between the United States */
11*d9805213SSascha Wildner /*  Department of Energy and the University of California. */
12*d9805213SSascha Wildner 
13*d9805213SSascha Wildner /* This file is part of flex */
14*d9805213SSascha Wildner 
15*d9805213SSascha Wildner /*  Redistribution and use in source and binary forms, with or without */
16*d9805213SSascha Wildner /*  modification, are permitted provided that the following conditions */
17*d9805213SSascha Wildner /*  are met: */
18*d9805213SSascha Wildner 
19*d9805213SSascha Wildner /*  1. Redistributions of source code must retain the above copyright */
20*d9805213SSascha Wildner /*     notice, this list of conditions and the following disclaimer. */
21*d9805213SSascha Wildner /*  2. Redistributions in binary form must reproduce the above copyright */
22*d9805213SSascha Wildner /*     notice, this list of conditions and the following disclaimer in the */
23*d9805213SSascha Wildner /*     documentation and/or other materials provided with the distribution. */
24*d9805213SSascha Wildner 
25*d9805213SSascha Wildner /*  Neither the name of the University nor the names of its contributors */
26*d9805213SSascha Wildner /*  may be used to endorse or promote products derived from this software */
27*d9805213SSascha Wildner /*  without specific prior written permission. */
28*d9805213SSascha Wildner 
29*d9805213SSascha Wildner /*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
30*d9805213SSascha Wildner /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
31*d9805213SSascha Wildner /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
32*d9805213SSascha Wildner /*  PURPOSE. */
33*d9805213SSascha Wildner 
34*d9805213SSascha Wildner 
35*d9805213SSascha Wildner #include "flexdef.h"
36*d9805213SSascha Wildner 
37*d9805213SSascha Wildner /* ccl2ecl - convert character classes to set of equivalence classes */
38*d9805213SSascha Wildner 
ccl2ecl(void)39*d9805213SSascha Wildner void    ccl2ecl (void)
40*d9805213SSascha Wildner {
41*d9805213SSascha Wildner 	int     i, ich, newlen, cclp, ccls, cclmec;
42*d9805213SSascha Wildner 
43*d9805213SSascha Wildner 	for (i = 1; i <= lastccl; ++i) {
44*d9805213SSascha Wildner 		/* We loop through each character class, and for each character
45*d9805213SSascha Wildner 		 * in the class, add the character's equivalence class to the
46*d9805213SSascha Wildner 		 * new "character" class we are creating.  Thus when we are all
47*d9805213SSascha Wildner 		 * done, character classes will really consist of collections
48*d9805213SSascha Wildner 		 * of equivalence classes
49*d9805213SSascha Wildner 		 */
50*d9805213SSascha Wildner 
51*d9805213SSascha Wildner 		newlen = 0;
52*d9805213SSascha Wildner 		cclp = cclmap[i];
53*d9805213SSascha Wildner 
54*d9805213SSascha Wildner 		for (ccls = 0; ccls < ccllen[i]; ++ccls) {
55*d9805213SSascha Wildner 			ich = ccltbl[cclp + ccls];
56*d9805213SSascha Wildner 			cclmec = ecgroup[ich];
57*d9805213SSascha Wildner 
58*d9805213SSascha Wildner 			if (cclmec > 0) {
59*d9805213SSascha Wildner 				/* Note: range 1..256 is mapped to 1..255,0 */
60*d9805213SSascha Wildner 				ccltbl[cclp + newlen] = (unsigned char) cclmec;
61*d9805213SSascha Wildner 				++newlen;
62*d9805213SSascha Wildner 			}
63*d9805213SSascha Wildner 		}
64*d9805213SSascha Wildner 
65*d9805213SSascha Wildner 		ccllen[i] = newlen;
66*d9805213SSascha Wildner 	}
67*d9805213SSascha Wildner }
68*d9805213SSascha Wildner 
69*d9805213SSascha Wildner 
70*d9805213SSascha Wildner /* cre8ecs - associate equivalence class numbers with class members
71*d9805213SSascha Wildner  *
72*d9805213SSascha Wildner  * fwd is the forward linked-list of equivalence class members.  bck
73*d9805213SSascha Wildner  * is the backward linked-list, and num is the number of class members.
74*d9805213SSascha Wildner  *
75*d9805213SSascha Wildner  * Returned is the number of classes.
76*d9805213SSascha Wildner  */
77*d9805213SSascha Wildner 
cre8ecs(int fwd[],int bck[],int num)78*d9805213SSascha Wildner int     cre8ecs (int fwd[], int bck[], int num)
79*d9805213SSascha Wildner {
80*d9805213SSascha Wildner 	int     i, j, numcl;
81*d9805213SSascha Wildner 
82*d9805213SSascha Wildner 	numcl = 0;
83*d9805213SSascha Wildner 
84*d9805213SSascha Wildner 	/* Create equivalence class numbers.  From now on, ABS( bck(x) )
85*d9805213SSascha Wildner 	 * is the equivalence class number for object x.  If bck(x)
86*d9805213SSascha Wildner 	 * is positive, then x is the representative of its equivalence
87*d9805213SSascha Wildner 	 * class.
88*d9805213SSascha Wildner 	 */
89*d9805213SSascha Wildner 	for (i = 1; i <= num; ++i)
90*d9805213SSascha Wildner 		if (bck[i] == NIL) {
91*d9805213SSascha Wildner 			bck[i] = ++numcl;
92*d9805213SSascha Wildner 			for (j = fwd[i]; j != NIL; j = fwd[j])
93*d9805213SSascha Wildner 				bck[j] = -numcl;
94*d9805213SSascha Wildner 		}
95*d9805213SSascha Wildner 
96*d9805213SSascha Wildner 	return numcl;
97*d9805213SSascha Wildner }
98*d9805213SSascha Wildner 
99*d9805213SSascha Wildner 
100*d9805213SSascha Wildner /* mkeccl - update equivalence classes based on character class xtions
101*d9805213SSascha Wildner  *
102*d9805213SSascha Wildner  * synopsis
103*d9805213SSascha Wildner  *    unsigned char ccls[];
104*d9805213SSascha Wildner  *    int lenccl, fwd[llsiz], bck[llsiz], llsiz, NUL_mapping;
105*d9805213SSascha Wildner  *    void mkeccl( unsigned char ccls[], int lenccl, int fwd[llsiz], int bck[llsiz],
106*d9805213SSascha Wildner  *			int llsiz, int NUL_mapping );
107*d9805213SSascha Wildner  *
108*d9805213SSascha Wildner  * ccls contains the elements of the character class, lenccl is the
109*d9805213SSascha Wildner  * number of elements in the ccl, fwd is the forward link-list of equivalent
110*d9805213SSascha Wildner  * characters, bck is the backward link-list, and llsiz size of the link-list.
111*d9805213SSascha Wildner  *
112*d9805213SSascha Wildner  * NUL_mapping is the value which NUL (0) should be mapped to.
113*d9805213SSascha Wildner  */
114*d9805213SSascha Wildner 
mkeccl(unsigned char ccls[],int lenccl,int fwd[],int bck[],int llsiz,int NUL_mapping)115*d9805213SSascha Wildner void    mkeccl (unsigned char ccls[], int lenccl, int fwd[], int bck[], int llsiz, int NUL_mapping)
116*d9805213SSascha Wildner {
117*d9805213SSascha Wildner 	int     cclp, oldec, newec;
118*d9805213SSascha Wildner 	int     cclm, i, j;
119*d9805213SSascha Wildner 	static unsigned char cclflags[CSIZE];	/* initialized to all '\0' */
120*d9805213SSascha Wildner 
121*d9805213SSascha Wildner 	/* Note that it doesn't matter whether or not the character class is
122*d9805213SSascha Wildner 	 * negated.  The same results will be obtained in either case.
123*d9805213SSascha Wildner 	 */
124*d9805213SSascha Wildner 
125*d9805213SSascha Wildner 	cclp = 0;
126*d9805213SSascha Wildner 
127*d9805213SSascha Wildner 	while (cclp < lenccl) {
128*d9805213SSascha Wildner 		cclm = ccls[cclp];
129*d9805213SSascha Wildner 
130*d9805213SSascha Wildner 		if (NUL_mapping && cclm == 0)
131*d9805213SSascha Wildner 			cclm = NUL_mapping;
132*d9805213SSascha Wildner 
133*d9805213SSascha Wildner 		oldec = bck[cclm];
134*d9805213SSascha Wildner 		newec = cclm;
135*d9805213SSascha Wildner 
136*d9805213SSascha Wildner 		j = cclp + 1;
137*d9805213SSascha Wildner 
138*d9805213SSascha Wildner 		for (i = fwd[cclm]; i != NIL && i <= llsiz; i = fwd[i]) {	/* look for the symbol in the character class */
139*d9805213SSascha Wildner 			for (; j < lenccl; ++j) {
140*d9805213SSascha Wildner 				int ccl_char;
141*d9805213SSascha Wildner 
142*d9805213SSascha Wildner 				if (NUL_mapping && ccls[j] == 0)
143*d9805213SSascha Wildner 					ccl_char = NUL_mapping;
144*d9805213SSascha Wildner 				else
145*d9805213SSascha Wildner 					ccl_char = ccls[j];
146*d9805213SSascha Wildner 
147*d9805213SSascha Wildner 				if (ccl_char > i)
148*d9805213SSascha Wildner 					break;
149*d9805213SSascha Wildner 
150*d9805213SSascha Wildner 				if (ccl_char == i && !cclflags[j]) {
151*d9805213SSascha Wildner 					/* We found an old companion of cclm
152*d9805213SSascha Wildner 					 * in the ccl.  Link it into the new
153*d9805213SSascha Wildner 					 * equivalence class and flag it as
154*d9805213SSascha Wildner 					 * having been processed.
155*d9805213SSascha Wildner 					 */
156*d9805213SSascha Wildner 
157*d9805213SSascha Wildner 					bck[i] = newec;
158*d9805213SSascha Wildner 					fwd[newec] = i;
159*d9805213SSascha Wildner 					newec = i;
160*d9805213SSascha Wildner 					/* Set flag so we don't reprocess. */
161*d9805213SSascha Wildner 					cclflags[j] = 1;
162*d9805213SSascha Wildner 
163*d9805213SSascha Wildner 					/* Get next equivalence class member. */
164*d9805213SSascha Wildner 					/* continue 2 */
165*d9805213SSascha Wildner 					goto next_pt;
166*d9805213SSascha Wildner 				}
167*d9805213SSascha Wildner 			}
168*d9805213SSascha Wildner 
169*d9805213SSascha Wildner 			/* Symbol isn't in character class.  Put it in the old
170*d9805213SSascha Wildner 			 * equivalence class.
171*d9805213SSascha Wildner 			 */
172*d9805213SSascha Wildner 
173*d9805213SSascha Wildner 			bck[i] = oldec;
174*d9805213SSascha Wildner 
175*d9805213SSascha Wildner 			if (oldec != NIL)
176*d9805213SSascha Wildner 				fwd[oldec] = i;
177*d9805213SSascha Wildner 
178*d9805213SSascha Wildner 			oldec = i;
179*d9805213SSascha Wildner 
180*d9805213SSascha Wildner 		      next_pt:;
181*d9805213SSascha Wildner 		}
182*d9805213SSascha Wildner 
183*d9805213SSascha Wildner 		if (bck[cclm] != NIL || oldec != bck[cclm]) {
184*d9805213SSascha Wildner 			bck[cclm] = NIL;
185*d9805213SSascha Wildner 			fwd[oldec] = NIL;
186*d9805213SSascha Wildner 		}
187*d9805213SSascha Wildner 
188*d9805213SSascha Wildner 		fwd[newec] = NIL;
189*d9805213SSascha Wildner 
190*d9805213SSascha Wildner 		/* Find next ccl member to process. */
191*d9805213SSascha Wildner 
192*d9805213SSascha Wildner 		for (++cclp; cclp < lenccl && cclflags[cclp]; ++cclp) {
193*d9805213SSascha Wildner 			/* Reset "doesn't need processing" flag. */
194*d9805213SSascha Wildner 			cclflags[cclp] = 0;
195*d9805213SSascha Wildner 		}
196*d9805213SSascha Wildner 	}
197*d9805213SSascha Wildner }
198*d9805213SSascha Wildner 
199*d9805213SSascha Wildner 
200*d9805213SSascha Wildner /* mkechar - create equivalence class for single character */
201*d9805213SSascha Wildner 
mkechar(int tch,int fwd[],int bck[])202*d9805213SSascha Wildner void    mkechar (int tch, int fwd[], int bck[])
203*d9805213SSascha Wildner {
204*d9805213SSascha Wildner 	/* If until now the character has been a proper subset of
205*d9805213SSascha Wildner 	 * an equivalence class, break it away to create a new ec
206*d9805213SSascha Wildner 	 */
207*d9805213SSascha Wildner 
208*d9805213SSascha Wildner 	if (fwd[tch] != NIL)
209*d9805213SSascha Wildner 		bck[fwd[tch]] = bck[tch];
210*d9805213SSascha Wildner 
211*d9805213SSascha Wildner 	if (bck[tch] != NIL)
212*d9805213SSascha Wildner 		fwd[bck[tch]] = fwd[tch];
213*d9805213SSascha Wildner 
214*d9805213SSascha Wildner 	fwd[tch] = NIL;
215*d9805213SSascha Wildner 	bck[tch] = NIL;
216*d9805213SSascha Wildner }
217