xref: /plan9/sys/src/cmd/grep/comp.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier #include	"grep.h"
2*7dd7cddfSDavid du Colombier 
3*7dd7cddfSDavid du Colombier /*
4*7dd7cddfSDavid du Colombier  * incremental compiler.
5*7dd7cddfSDavid du Colombier  * add the branch c to the
6*7dd7cddfSDavid du Colombier  * state s.
7*7dd7cddfSDavid du Colombier  */
8*7dd7cddfSDavid du Colombier void
9*7dd7cddfSDavid du Colombier increment(State *s, int c)
10*7dd7cddfSDavid du Colombier {
11*7dd7cddfSDavid du Colombier 	int i;
12*7dd7cddfSDavid du Colombier 	State *t, **tt;
13*7dd7cddfSDavid du Colombier 	Re *re1, *re2;
14*7dd7cddfSDavid du Colombier 
15*7dd7cddfSDavid du Colombier 	nfollow = 0;
16*7dd7cddfSDavid du Colombier 	gen++;
17*7dd7cddfSDavid du Colombier 	matched = 0;
18*7dd7cddfSDavid du Colombier 	for(i=0; i<s->count; i++)
19*7dd7cddfSDavid du Colombier 		fol1(s->re[i], c);
20*7dd7cddfSDavid du Colombier 	qsort(follow, nfollow, sizeof(*follow), fcmp);
21*7dd7cddfSDavid du Colombier 	for(tt=&state0; t = *tt;) {
22*7dd7cddfSDavid du Colombier 		if(t->count > nfollow) {
23*7dd7cddfSDavid du Colombier 			tt = &t->linkleft;
24*7dd7cddfSDavid du Colombier 			goto cont;
25*7dd7cddfSDavid du Colombier 		}
26*7dd7cddfSDavid du Colombier 		if(t->count < nfollow) {
27*7dd7cddfSDavid du Colombier 			tt = &t->linkright;
28*7dd7cddfSDavid du Colombier 			goto cont;
29*7dd7cddfSDavid du Colombier 		}
30*7dd7cddfSDavid du Colombier 		for(i=0; i<nfollow; i++) {
31*7dd7cddfSDavid du Colombier 			re1 = t->re[i];
32*7dd7cddfSDavid du Colombier 			re2 = follow[i];
33*7dd7cddfSDavid du Colombier 			if(re1 > re2) {
34*7dd7cddfSDavid du Colombier 				tt = &t->linkleft;
35*7dd7cddfSDavid du Colombier 				goto cont;
36*7dd7cddfSDavid du Colombier 			}
37*7dd7cddfSDavid du Colombier 			if(re1 < re2) {
38*7dd7cddfSDavid du Colombier 				tt = &t->linkright;
39*7dd7cddfSDavid du Colombier 				goto cont;
40*7dd7cddfSDavid du Colombier 			}
41*7dd7cddfSDavid du Colombier 		}
42*7dd7cddfSDavid du Colombier 		if(!!matched && !t->match) {
43*7dd7cddfSDavid du Colombier 			tt = &t->linkleft;
44*7dd7cddfSDavid du Colombier 			goto cont;
45*7dd7cddfSDavid du Colombier 		}
46*7dd7cddfSDavid du Colombier 		if(!matched && !!t->match) {
47*7dd7cddfSDavid du Colombier 			tt = &t->linkright;
48*7dd7cddfSDavid du Colombier 			goto cont;
49*7dd7cddfSDavid du Colombier 		}
50*7dd7cddfSDavid du Colombier 		s->next[c] = t;
51*7dd7cddfSDavid du Colombier 		return;
52*7dd7cddfSDavid du Colombier 	cont:;
53*7dd7cddfSDavid du Colombier 	}
54*7dd7cddfSDavid du Colombier 
55*7dd7cddfSDavid du Colombier 	t = sal(nfollow);
56*7dd7cddfSDavid du Colombier 	*tt = t;
57*7dd7cddfSDavid du Colombier 	for(i=0; i<nfollow; i++) {
58*7dd7cddfSDavid du Colombier 		re1 = follow[i];
59*7dd7cddfSDavid du Colombier 		t->re[i] = re1;
60*7dd7cddfSDavid du Colombier 	}
61*7dd7cddfSDavid du Colombier 	s->next[c] = t;
62*7dd7cddfSDavid du Colombier 	t->match = matched;
63*7dd7cddfSDavid du Colombier }
64*7dd7cddfSDavid du Colombier 
65*7dd7cddfSDavid du Colombier int
66*7dd7cddfSDavid du Colombier fcmp(void *va, void *vb)
67*7dd7cddfSDavid du Colombier {
68*7dd7cddfSDavid du Colombier 	Re **aa, **bb;
69*7dd7cddfSDavid du Colombier 	Re *a, *b;
70*7dd7cddfSDavid du Colombier 
71*7dd7cddfSDavid du Colombier 	aa = va;
72*7dd7cddfSDavid du Colombier 	bb = vb;
73*7dd7cddfSDavid du Colombier 	a = *aa;
74*7dd7cddfSDavid du Colombier 	b = *bb;
75*7dd7cddfSDavid du Colombier 	if(a > b)
76*7dd7cddfSDavid du Colombier 		return 1;
77*7dd7cddfSDavid du Colombier 	if(a < b)
78*7dd7cddfSDavid du Colombier 		return -1;
79*7dd7cddfSDavid du Colombier 	return 0;
80*7dd7cddfSDavid du Colombier }
81*7dd7cddfSDavid du Colombier 
82*7dd7cddfSDavid du Colombier void
83*7dd7cddfSDavid du Colombier fol1(Re *r, int c)
84*7dd7cddfSDavid du Colombier {
85*7dd7cddfSDavid du Colombier 	Re *r1;
86*7dd7cddfSDavid du Colombier 
87*7dd7cddfSDavid du Colombier loop:
88*7dd7cddfSDavid du Colombier 	if(r->gen == gen)
89*7dd7cddfSDavid du Colombier 		return;
90*7dd7cddfSDavid du Colombier 	if(nfollow >= maxfollow)
91*7dd7cddfSDavid du Colombier 		error("nfollow");
92*7dd7cddfSDavid du Colombier 	r->gen = gen;
93*7dd7cddfSDavid du Colombier 	switch(r->type) {
94*7dd7cddfSDavid du Colombier 	default:
95*7dd7cddfSDavid du Colombier 		error("fol1");
96*7dd7cddfSDavid du Colombier 
97*7dd7cddfSDavid du Colombier 	case Tcase:
98*7dd7cddfSDavid du Colombier 		if(c >= 0 && c < 256)
99*7dd7cddfSDavid du Colombier 		if(r1 = r->cases[c])
100*7dd7cddfSDavid du Colombier 			follow[nfollow++] = r1;
101*7dd7cddfSDavid du Colombier 		if(r = r->next)
102*7dd7cddfSDavid du Colombier 			goto loop;
103*7dd7cddfSDavid du Colombier 		break;
104*7dd7cddfSDavid du Colombier 
105*7dd7cddfSDavid du Colombier 	case Talt:
106*7dd7cddfSDavid du Colombier 	case Tor:
107*7dd7cddfSDavid du Colombier 		fol1(r->alt, c);
108*7dd7cddfSDavid du Colombier 		r = r->next;
109*7dd7cddfSDavid du Colombier 		goto loop;
110*7dd7cddfSDavid du Colombier 
111*7dd7cddfSDavid du Colombier 	case Tbegin:
112*7dd7cddfSDavid du Colombier 		if(c == '\n' || c == Cbegin)
113*7dd7cddfSDavid du Colombier 			follow[nfollow++] = r->next;
114*7dd7cddfSDavid du Colombier 		break;
115*7dd7cddfSDavid du Colombier 
116*7dd7cddfSDavid du Colombier 	case Tend:
117*7dd7cddfSDavid du Colombier 		if(c == '\n')
118*7dd7cddfSDavid du Colombier 			matched = 1;
119*7dd7cddfSDavid du Colombier 		break;
120*7dd7cddfSDavid du Colombier 
121*7dd7cddfSDavid du Colombier 	case Tclass:
122*7dd7cddfSDavid du Colombier 		if(c >= r->lo && c <= r->hi)
123*7dd7cddfSDavid du Colombier 			follow[nfollow++] = r->next;
124*7dd7cddfSDavid du Colombier 		break;
125*7dd7cddfSDavid du Colombier 	}
126*7dd7cddfSDavid du Colombier }
127*7dd7cddfSDavid du Colombier 
128*7dd7cddfSDavid du Colombier Rune	tab1[] =
129*7dd7cddfSDavid du Colombier {
130*7dd7cddfSDavid du Colombier 	0x007f,
131*7dd7cddfSDavid du Colombier 	0x07ff,
132*7dd7cddfSDavid du Colombier };
133*7dd7cddfSDavid du Colombier Rune	tab2[] =
134*7dd7cddfSDavid du Colombier {
135*7dd7cddfSDavid du Colombier 	0x003f,
136*7dd7cddfSDavid du Colombier 	0x0fff,
137*7dd7cddfSDavid du Colombier };
138*7dd7cddfSDavid du Colombier 
139*7dd7cddfSDavid du Colombier Re2
140*7dd7cddfSDavid du Colombier rclass(Rune p0, Rune p1)
141*7dd7cddfSDavid du Colombier {
142*7dd7cddfSDavid du Colombier 	char xc0[6], xc1[6];
143*7dd7cddfSDavid du Colombier 	int i, n, m;
144*7dd7cddfSDavid du Colombier 	Re2 x;
145*7dd7cddfSDavid du Colombier 
146*7dd7cddfSDavid du Colombier 	if(p0 > p1)
147*7dd7cddfSDavid du Colombier 		return re2char(0xff, 0xff);	// no match
148*7dd7cddfSDavid du Colombier 
149*7dd7cddfSDavid du Colombier 	/*
150*7dd7cddfSDavid du Colombier 	 * bust range into same length
151*7dd7cddfSDavid du Colombier 	 * character sequences
152*7dd7cddfSDavid du Colombier 	 */
153*7dd7cddfSDavid du Colombier 	for(i=0; i<nelem(tab1); i++) {
154*7dd7cddfSDavid du Colombier 		m = tab1[i];
155*7dd7cddfSDavid du Colombier 		if(p0 <= m && p1 > m)
156*7dd7cddfSDavid du Colombier 			return re2or(rclass(p0, m), rclass(m+1, p1));
157*7dd7cddfSDavid du Colombier 	}
158*7dd7cddfSDavid du Colombier 
159*7dd7cddfSDavid du Colombier 	/*
160*7dd7cddfSDavid du Colombier 	 * bust range into part of a single page
161*7dd7cddfSDavid du Colombier 	 * or into full pages
162*7dd7cddfSDavid du Colombier 	 */
163*7dd7cddfSDavid du Colombier 	for(i=0; i<nelem(tab2); i++) {
164*7dd7cddfSDavid du Colombier 		m = tab2[i];
165*7dd7cddfSDavid du Colombier 		if((p0 & ~m) != (p1 & ~m)) {
166*7dd7cddfSDavid du Colombier 			if((p0 & m) != 0)
167*7dd7cddfSDavid du Colombier 				return re2or(rclass(p0, p0|m), rclass((p0|m)+1, p1));
168*7dd7cddfSDavid du Colombier 			if((p1 & m) != m)
169*7dd7cddfSDavid du Colombier 				return re2or(rclass(p0, (p1&~m)-1), rclass(p1&~m, p1));
170*7dd7cddfSDavid du Colombier 		}
171*7dd7cddfSDavid du Colombier 	}
172*7dd7cddfSDavid du Colombier 
173*7dd7cddfSDavid du Colombier 	n = runetochar(xc0, &p0);
174*7dd7cddfSDavid du Colombier 	i = runetochar(xc1, &p1);
175*7dd7cddfSDavid du Colombier 	if(i != n)
176*7dd7cddfSDavid du Colombier 		error("length");
177*7dd7cddfSDavid du Colombier 
178*7dd7cddfSDavid du Colombier 	x = re2char(xc0[0], xc1[0]);
179*7dd7cddfSDavid du Colombier 	for(i=1; i<n; i++)
180*7dd7cddfSDavid du Colombier 		x = re2cat(x, re2char(xc0[i], xc1[i]));
181*7dd7cddfSDavid du Colombier 	return x;
182*7dd7cddfSDavid du Colombier }
183*7dd7cddfSDavid du Colombier 
184*7dd7cddfSDavid du Colombier int
185*7dd7cddfSDavid du Colombier pcmp(void *va, void *vb)
186*7dd7cddfSDavid du Colombier {
187*7dd7cddfSDavid du Colombier 	int n;
188*7dd7cddfSDavid du Colombier 	Rune *a, *b;
189*7dd7cddfSDavid du Colombier 
190*7dd7cddfSDavid du Colombier 	a = va;
191*7dd7cddfSDavid du Colombier 	b = vb;
192*7dd7cddfSDavid du Colombier 
193*7dd7cddfSDavid du Colombier 	n = a[0] - b[0];
194*7dd7cddfSDavid du Colombier 	if(n)
195*7dd7cddfSDavid du Colombier 		return n;
196*7dd7cddfSDavid du Colombier 	return a[1] - b[1];
197*7dd7cddfSDavid du Colombier }
198*7dd7cddfSDavid du Colombier 
199*7dd7cddfSDavid du Colombier /*
200*7dd7cddfSDavid du Colombier  * convert character chass into
201*7dd7cddfSDavid du Colombier  * run-pair ranges of matches.
202*7dd7cddfSDavid du Colombier  * this is 10646/utf specific and
203*7dd7cddfSDavid du Colombier  * needs to be changed for some
204*7dd7cddfSDavid du Colombier  * other input character set.
205*7dd7cddfSDavid du Colombier  * this is the key to a fast
206*7dd7cddfSDavid du Colombier  * regular search of characters
207*7dd7cddfSDavid du Colombier  * by looking at sequential bytes.
208*7dd7cddfSDavid du Colombier  */
209*7dd7cddfSDavid du Colombier Re2
210*7dd7cddfSDavid du Colombier re2class(char *s)
211*7dd7cddfSDavid du Colombier {
212*7dd7cddfSDavid du Colombier 	Rune pairs[200], *p, *q, ov;
213*7dd7cddfSDavid du Colombier 	int nc;
214*7dd7cddfSDavid du Colombier 	Re2 x;
215*7dd7cddfSDavid du Colombier 
216*7dd7cddfSDavid du Colombier 	nc = 0;
217*7dd7cddfSDavid du Colombier 	if(*s == '^') {
218*7dd7cddfSDavid du Colombier 		nc = 1;
219*7dd7cddfSDavid du Colombier 		s++;
220*7dd7cddfSDavid du Colombier 	}
221*7dd7cddfSDavid du Colombier 
222*7dd7cddfSDavid du Colombier 	p = pairs;
223*7dd7cddfSDavid du Colombier 	s += chartorune(p, s);
224*7dd7cddfSDavid du Colombier 	for(;;) {
225*7dd7cddfSDavid du Colombier 		if(*p == '\\')
226*7dd7cddfSDavid du Colombier 			s += chartorune(p, s);
227*7dd7cddfSDavid du Colombier 		if(*p == 0)
228*7dd7cddfSDavid du Colombier 			break;
229*7dd7cddfSDavid du Colombier 		p[1] = *p;
230*7dd7cddfSDavid du Colombier 		p += 2;
231*7dd7cddfSDavid du Colombier 		s += chartorune(p, s);
232*7dd7cddfSDavid du Colombier 		if(*p != '-')
233*7dd7cddfSDavid du Colombier 			continue;
234*7dd7cddfSDavid du Colombier 		s += chartorune(p, s);
235*7dd7cddfSDavid du Colombier 		if(*p == '\\')
236*7dd7cddfSDavid du Colombier 			s += chartorune(p, s);
237*7dd7cddfSDavid du Colombier 		if(*p == 0)
238*7dd7cddfSDavid du Colombier 			break;
239*7dd7cddfSDavid du Colombier 		p[-1] = *p;
240*7dd7cddfSDavid du Colombier 		s += chartorune(p, s);
241*7dd7cddfSDavid du Colombier 	}
242*7dd7cddfSDavid du Colombier 	*p = 0;
243*7dd7cddfSDavid du Colombier 	qsort(pairs, (p-pairs)/2, 2*sizeof(*pairs), pcmp);
244*7dd7cddfSDavid du Colombier 
245*7dd7cddfSDavid du Colombier 	q = pairs;
246*7dd7cddfSDavid du Colombier 	for(p=pairs+2; *p; p+=2) {
247*7dd7cddfSDavid du Colombier 		if(p[0] > p[1])
248*7dd7cddfSDavid du Colombier 			continue;
249*7dd7cddfSDavid du Colombier 		if(p[0] > q[1] || p[1] < q[0]) {
250*7dd7cddfSDavid du Colombier 			q[2] = p[0];
251*7dd7cddfSDavid du Colombier 			q[3] = p[1];
252*7dd7cddfSDavid du Colombier 			q += 2;
253*7dd7cddfSDavid du Colombier 			continue;
254*7dd7cddfSDavid du Colombier 		}
255*7dd7cddfSDavid du Colombier 		if(p[0] < q[0])
256*7dd7cddfSDavid du Colombier 			q[0] = p[0];
257*7dd7cddfSDavid du Colombier 		if(p[1] > q[1])
258*7dd7cddfSDavid du Colombier 			q[1] = p[1];
259*7dd7cddfSDavid du Colombier 	}
260*7dd7cddfSDavid du Colombier 	q[2] = 0;
261*7dd7cddfSDavid du Colombier 
262*7dd7cddfSDavid du Colombier 	p = pairs;
263*7dd7cddfSDavid du Colombier 	if(nc) {
264*7dd7cddfSDavid du Colombier 		x = rclass(0, p[0]-1);
265*7dd7cddfSDavid du Colombier 		ov = p[1]+1;
266*7dd7cddfSDavid du Colombier 		for(p+=2; *p; p+=2) {
267*7dd7cddfSDavid du Colombier 			x = re2or(x, rclass(ov, p[0]-1));
268*7dd7cddfSDavid du Colombier 			ov = p[1]+1;
269*7dd7cddfSDavid du Colombier 		}
270*7dd7cddfSDavid du Colombier 		x = re2or(x, rclass(ov, 0xffff));
271*7dd7cddfSDavid du Colombier 	} else {
272*7dd7cddfSDavid du Colombier 		x = rclass(p[0], p[1]);
273*7dd7cddfSDavid du Colombier 		for(p+=2; *p; p+=2)
274*7dd7cddfSDavid du Colombier 			x = re2or(x, rclass(p[0], p[1]));
275*7dd7cddfSDavid du Colombier 	}
276*7dd7cddfSDavid du Colombier 	return x;
277*7dd7cddfSDavid du Colombier }
278