xref: /plan9/sys/src/cmd/grep/comp.c (revision 82726826a7b3d40fb66339b4b0e95b60314f98b9)
17dd7cddfSDavid du Colombier #include	"grep.h"
27dd7cddfSDavid du Colombier 
37dd7cddfSDavid du Colombier /*
47dd7cddfSDavid du Colombier  * incremental compiler.
57dd7cddfSDavid du Colombier  * add the branch c to the
67dd7cddfSDavid du Colombier  * state s.
77dd7cddfSDavid du Colombier  */
87dd7cddfSDavid du Colombier void
increment(State * s,int c)97dd7cddfSDavid du Colombier increment(State *s, int c)
107dd7cddfSDavid du Colombier {
117dd7cddfSDavid du Colombier 	int i;
127dd7cddfSDavid du Colombier 	State *t, **tt;
137dd7cddfSDavid du Colombier 	Re *re1, *re2;
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier 	nfollow = 0;
167dd7cddfSDavid du Colombier 	gen++;
177dd7cddfSDavid du Colombier 	matched = 0;
187dd7cddfSDavid du Colombier 	for(i=0; i<s->count; i++)
197dd7cddfSDavid du Colombier 		fol1(s->re[i], c);
207dd7cddfSDavid du Colombier 	qsort(follow, nfollow, sizeof(*follow), fcmp);
217dd7cddfSDavid du Colombier 	for(tt=&state0; t = *tt;) {
227dd7cddfSDavid du Colombier 		if(t->count > nfollow) {
237dd7cddfSDavid du Colombier 			tt = &t->linkleft;
247dd7cddfSDavid du Colombier 			goto cont;
257dd7cddfSDavid du Colombier 		}
267dd7cddfSDavid du Colombier 		if(t->count < nfollow) {
277dd7cddfSDavid du Colombier 			tt = &t->linkright;
287dd7cddfSDavid du Colombier 			goto cont;
297dd7cddfSDavid du Colombier 		}
307dd7cddfSDavid du Colombier 		for(i=0; i<nfollow; i++) {
317dd7cddfSDavid du Colombier 			re1 = t->re[i];
327dd7cddfSDavid du Colombier 			re2 = follow[i];
337dd7cddfSDavid du Colombier 			if(re1 > re2) {
347dd7cddfSDavid du Colombier 				tt = &t->linkleft;
357dd7cddfSDavid du Colombier 				goto cont;
367dd7cddfSDavid du Colombier 			}
377dd7cddfSDavid du Colombier 			if(re1 < re2) {
387dd7cddfSDavid du Colombier 				tt = &t->linkright;
397dd7cddfSDavid du Colombier 				goto cont;
407dd7cddfSDavid du Colombier 			}
417dd7cddfSDavid du Colombier 		}
427dd7cddfSDavid du Colombier 		if(!!matched && !t->match) {
437dd7cddfSDavid du Colombier 			tt = &t->linkleft;
447dd7cddfSDavid du Colombier 			goto cont;
457dd7cddfSDavid du Colombier 		}
467dd7cddfSDavid du Colombier 		if(!matched && !!t->match) {
477dd7cddfSDavid du Colombier 			tt = &t->linkright;
487dd7cddfSDavid du Colombier 			goto cont;
497dd7cddfSDavid du Colombier 		}
507dd7cddfSDavid du Colombier 		s->next[c] = t;
517dd7cddfSDavid du Colombier 		return;
527dd7cddfSDavid du Colombier 	cont:;
537dd7cddfSDavid du Colombier 	}
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	t = sal(nfollow);
567dd7cddfSDavid du Colombier 	*tt = t;
577dd7cddfSDavid du Colombier 	for(i=0; i<nfollow; i++) {
587dd7cddfSDavid du Colombier 		re1 = follow[i];
597dd7cddfSDavid du Colombier 		t->re[i] = re1;
607dd7cddfSDavid du Colombier 	}
617dd7cddfSDavid du Colombier 	s->next[c] = t;
627dd7cddfSDavid du Colombier 	t->match = matched;
637dd7cddfSDavid du Colombier }
647dd7cddfSDavid du Colombier 
657dd7cddfSDavid du Colombier int
fcmp(void * va,void * vb)667dd7cddfSDavid du Colombier fcmp(void *va, void *vb)
677dd7cddfSDavid du Colombier {
687dd7cddfSDavid du Colombier 	Re **aa, **bb;
697dd7cddfSDavid du Colombier 	Re *a, *b;
707dd7cddfSDavid du Colombier 
717dd7cddfSDavid du Colombier 	aa = va;
727dd7cddfSDavid du Colombier 	bb = vb;
737dd7cddfSDavid du Colombier 	a = *aa;
747dd7cddfSDavid du Colombier 	b = *bb;
757dd7cddfSDavid du Colombier 	if(a > b)
767dd7cddfSDavid du Colombier 		return 1;
777dd7cddfSDavid du Colombier 	if(a < b)
787dd7cddfSDavid du Colombier 		return -1;
797dd7cddfSDavid du Colombier 	return 0;
807dd7cddfSDavid du Colombier }
817dd7cddfSDavid du Colombier 
827dd7cddfSDavid du Colombier void
fol1(Re * r,int c)837dd7cddfSDavid du Colombier fol1(Re *r, int c)
847dd7cddfSDavid du Colombier {
857dd7cddfSDavid du Colombier 	Re *r1;
867dd7cddfSDavid du Colombier 
877dd7cddfSDavid du Colombier loop:
887dd7cddfSDavid du Colombier 	if(r->gen == gen)
897dd7cddfSDavid du Colombier 		return;
907dd7cddfSDavid du Colombier 	if(nfollow >= maxfollow)
917dd7cddfSDavid du Colombier 		error("nfollow");
927dd7cddfSDavid du Colombier 	r->gen = gen;
937dd7cddfSDavid du Colombier 	switch(r->type) {
947dd7cddfSDavid du Colombier 	default:
957dd7cddfSDavid du Colombier 		error("fol1");
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier 	case Tcase:
987dd7cddfSDavid du Colombier 		if(c >= 0 && c < 256)
997dd7cddfSDavid du Colombier 		if(r1 = r->cases[c])
1007dd7cddfSDavid du Colombier 			follow[nfollow++] = r1;
1017dd7cddfSDavid du Colombier 		if(r = r->next)
1027dd7cddfSDavid du Colombier 			goto loop;
1037dd7cddfSDavid du Colombier 		break;
1047dd7cddfSDavid du Colombier 
1057dd7cddfSDavid du Colombier 	case Talt:
1067dd7cddfSDavid du Colombier 	case Tor:
1077dd7cddfSDavid du Colombier 		fol1(r->alt, c);
1087dd7cddfSDavid du Colombier 		r = r->next;
1097dd7cddfSDavid du Colombier 		goto loop;
1107dd7cddfSDavid du Colombier 
1117dd7cddfSDavid du Colombier 	case Tbegin:
1127dd7cddfSDavid du Colombier 		if(c == '\n' || c == Cbegin)
1137dd7cddfSDavid du Colombier 			follow[nfollow++] = r->next;
1147dd7cddfSDavid du Colombier 		break;
1157dd7cddfSDavid du Colombier 
1167dd7cddfSDavid du Colombier 	case Tend:
11774f16c81SDavid du Colombier 		if(c == '\n') {
11874f16c81SDavid du Colombier 			if(r->next == 0) {
1197dd7cddfSDavid du Colombier 				matched = 1;
1207dd7cddfSDavid du Colombier 				break;
12174f16c81SDavid du Colombier 			}
12274f16c81SDavid du Colombier 			r = r->next;
12374f16c81SDavid du Colombier 			goto loop;
12474f16c81SDavid du Colombier 		}
12574f16c81SDavid du Colombier 		break;
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier 	case Tclass:
1287dd7cddfSDavid du Colombier 		if(c >= r->lo && c <= r->hi)
1297dd7cddfSDavid du Colombier 			follow[nfollow++] = r->next;
1307dd7cddfSDavid du Colombier 		break;
1317dd7cddfSDavid du Colombier 	}
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier Rune	tab1[] =
1357dd7cddfSDavid du Colombier {
1367dd7cddfSDavid du Colombier 	0x007f,
1377dd7cddfSDavid du Colombier 	0x07ff,
1387dd7cddfSDavid du Colombier };
1397dd7cddfSDavid du Colombier Rune	tab2[] =
1407dd7cddfSDavid du Colombier {
1417dd7cddfSDavid du Colombier 	0x003f,
1427dd7cddfSDavid du Colombier 	0x0fff,
1437dd7cddfSDavid du Colombier };
1447dd7cddfSDavid du Colombier 
1457dd7cddfSDavid du Colombier Re2
rclass(Rune p0,Rune p1)1467dd7cddfSDavid du Colombier rclass(Rune p0, Rune p1)
1477dd7cddfSDavid du Colombier {
1487dd7cddfSDavid du Colombier 	char xc0[6], xc1[6];
1497dd7cddfSDavid du Colombier 	int i, n, m;
1507dd7cddfSDavid du Colombier 	Re2 x;
1517dd7cddfSDavid du Colombier 
1527dd7cddfSDavid du Colombier 	if(p0 > p1)
1537dd7cddfSDavid du Colombier 		return re2char(0xff, 0xff);	// no match
1547dd7cddfSDavid du Colombier 
1557dd7cddfSDavid du Colombier 	/*
1567dd7cddfSDavid du Colombier 	 * bust range into same length
1577dd7cddfSDavid du Colombier 	 * character sequences
1587dd7cddfSDavid du Colombier 	 */
1597dd7cddfSDavid du Colombier 	for(i=0; i<nelem(tab1); i++) {
1607dd7cddfSDavid du Colombier 		m = tab1[i];
1617dd7cddfSDavid du Colombier 		if(p0 <= m && p1 > m)
1627dd7cddfSDavid du Colombier 			return re2or(rclass(p0, m), rclass(m+1, p1));
1637dd7cddfSDavid du Colombier 	}
1647dd7cddfSDavid du Colombier 
1657dd7cddfSDavid du Colombier 	/*
1667dd7cddfSDavid du Colombier 	 * bust range into part of a single page
1677dd7cddfSDavid du Colombier 	 * or into full pages
1687dd7cddfSDavid du Colombier 	 */
1697dd7cddfSDavid du Colombier 	for(i=0; i<nelem(tab2); i++) {
1707dd7cddfSDavid du Colombier 		m = tab2[i];
1717dd7cddfSDavid du Colombier 		if((p0 & ~m) != (p1 & ~m)) {
1727dd7cddfSDavid du Colombier 			if((p0 & m) != 0)
1737dd7cddfSDavid du Colombier 				return re2or(rclass(p0, p0|m), rclass((p0|m)+1, p1));
1747dd7cddfSDavid du Colombier 			if((p1 & m) != m)
1757dd7cddfSDavid du Colombier 				return re2or(rclass(p0, (p1&~m)-1), rclass(p1&~m, p1));
1767dd7cddfSDavid du Colombier 		}
1777dd7cddfSDavid du Colombier 	}
1787dd7cddfSDavid du Colombier 
1797dd7cddfSDavid du Colombier 	n = runetochar(xc0, &p0);
1807dd7cddfSDavid du Colombier 	i = runetochar(xc1, &p1);
1817dd7cddfSDavid du Colombier 	if(i != n)
1827dd7cddfSDavid du Colombier 		error("length");
1837dd7cddfSDavid du Colombier 
1847dd7cddfSDavid du Colombier 	x = re2char(xc0[0], xc1[0]);
1857dd7cddfSDavid du Colombier 	for(i=1; i<n; i++)
1867dd7cddfSDavid du Colombier 		x = re2cat(x, re2char(xc0[i], xc1[i]));
1877dd7cddfSDavid du Colombier 	return x;
1887dd7cddfSDavid du Colombier }
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier int
pcmp(void * va,void * vb)1917dd7cddfSDavid du Colombier pcmp(void *va, void *vb)
1927dd7cddfSDavid du Colombier {
1937dd7cddfSDavid du Colombier 	int n;
1947dd7cddfSDavid du Colombier 	Rune *a, *b;
1957dd7cddfSDavid du Colombier 
1967dd7cddfSDavid du Colombier 	a = va;
1977dd7cddfSDavid du Colombier 	b = vb;
1987dd7cddfSDavid du Colombier 
1997dd7cddfSDavid du Colombier 	n = a[0] - b[0];
2007dd7cddfSDavid du Colombier 	if(n)
2017dd7cddfSDavid du Colombier 		return n;
2027dd7cddfSDavid du Colombier 	return a[1] - b[1];
2037dd7cddfSDavid du Colombier }
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier /*
2067dd7cddfSDavid du Colombier  * convert character chass into
2077dd7cddfSDavid du Colombier  * run-pair ranges of matches.
2087dd7cddfSDavid du Colombier  * this is 10646/utf specific and
2097dd7cddfSDavid du Colombier  * needs to be changed for some
2107dd7cddfSDavid du Colombier  * other input character set.
2117dd7cddfSDavid du Colombier  * this is the key to a fast
2127dd7cddfSDavid du Colombier  * regular search of characters
2137dd7cddfSDavid du Colombier  * by looking at sequential bytes.
2147dd7cddfSDavid du Colombier  */
2157dd7cddfSDavid du Colombier Re2
re2class(char * s)2167dd7cddfSDavid du Colombier re2class(char *s)
2177dd7cddfSDavid du Colombier {
218d1be6b08SDavid du Colombier 	Rune pairs[200+2], *p, *q, ov;
2197dd7cddfSDavid du Colombier 	int nc;
2207dd7cddfSDavid du Colombier 	Re2 x;
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier 	nc = 0;
2237dd7cddfSDavid du Colombier 	if(*s == '^') {
2247dd7cddfSDavid du Colombier 		nc = 1;
2257dd7cddfSDavid du Colombier 		s++;
2267dd7cddfSDavid du Colombier 	}
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier 	p = pairs;
2297dd7cddfSDavid du Colombier 	s += chartorune(p, s);
2307dd7cddfSDavid du Colombier 	for(;;) {
2317dd7cddfSDavid du Colombier 		if(*p == '\\')
2327dd7cddfSDavid du Colombier 			s += chartorune(p, s);
2337dd7cddfSDavid du Colombier 		if(*p == 0)
2347dd7cddfSDavid du Colombier 			break;
2357dd7cddfSDavid du Colombier 		p[1] = *p;
2367dd7cddfSDavid du Colombier 		p += 2;
237d1be6b08SDavid du Colombier 		if(p >= pairs + nelem(pairs) - 2)
238d1be6b08SDavid du Colombier 			error("class too big");
2397dd7cddfSDavid du Colombier 		s += chartorune(p, s);
2407dd7cddfSDavid du Colombier 		if(*p != '-')
2417dd7cddfSDavid du Colombier 			continue;
2427dd7cddfSDavid du Colombier 		s += chartorune(p, s);
2437dd7cddfSDavid du Colombier 		if(*p == '\\')
2447dd7cddfSDavid du Colombier 			s += chartorune(p, s);
2457dd7cddfSDavid du Colombier 		if(*p == 0)
2467dd7cddfSDavid du Colombier 			break;
2477dd7cddfSDavid du Colombier 		p[-1] = *p;
2487dd7cddfSDavid du Colombier 		s += chartorune(p, s);
2497dd7cddfSDavid du Colombier 	}
2507dd7cddfSDavid du Colombier 	*p = 0;
2517dd7cddfSDavid du Colombier 	qsort(pairs, (p-pairs)/2, 2*sizeof(*pairs), pcmp);
2527dd7cddfSDavid du Colombier 
2537dd7cddfSDavid du Colombier 	q = pairs;
2547dd7cddfSDavid du Colombier 	for(p=pairs+2; *p; p+=2) {
2557dd7cddfSDavid du Colombier 		if(p[0] > p[1])
2567dd7cddfSDavid du Colombier 			continue;
2577dd7cddfSDavid du Colombier 		if(p[0] > q[1] || p[1] < q[0]) {
2587dd7cddfSDavid du Colombier 			q[2] = p[0];
2597dd7cddfSDavid du Colombier 			q[3] = p[1];
2607dd7cddfSDavid du Colombier 			q += 2;
2617dd7cddfSDavid du Colombier 			continue;
2627dd7cddfSDavid du Colombier 		}
2637dd7cddfSDavid du Colombier 		if(p[0] < q[0])
2647dd7cddfSDavid du Colombier 			q[0] = p[0];
2657dd7cddfSDavid du Colombier 		if(p[1] > q[1])
2667dd7cddfSDavid du Colombier 			q[1] = p[1];
2677dd7cddfSDavid du Colombier 	}
2687dd7cddfSDavid du Colombier 	q[2] = 0;
2697dd7cddfSDavid du Colombier 
2707dd7cddfSDavid du Colombier 	p = pairs;
2717dd7cddfSDavid du Colombier 	if(nc) {
2727dd7cddfSDavid du Colombier 		x = rclass(0, p[0]-1);
2737dd7cddfSDavid du Colombier 		ov = p[1]+1;
2747dd7cddfSDavid du Colombier 		for(p+=2; *p; p+=2) {
2757dd7cddfSDavid du Colombier 			x = re2or(x, rclass(ov, p[0]-1));
2767dd7cddfSDavid du Colombier 			ov = p[1]+1;
2777dd7cddfSDavid du Colombier 		}
278*82726826SDavid du Colombier 		x = re2or(x, rclass(ov, Runemask));
2797dd7cddfSDavid du Colombier 	} else {
2807dd7cddfSDavid du Colombier 		x = rclass(p[0], p[1]);
2817dd7cddfSDavid du Colombier 		for(p+=2; *p; p+=2)
2827dd7cddfSDavid du Colombier 			x = re2or(x, rclass(p[0], p[1]));
2837dd7cddfSDavid du Colombier 	}
2847dd7cddfSDavid du Colombier 	return x;
2857dd7cddfSDavid du Colombier }
286