xref: /csrg-svn/old/sdb/re.c (revision 1348)
1*1348Sbill static	char sccsid[] = "@(#)re.c 4.1 10/09/80";
2*1348Sbill #include "head.h"
3*1348Sbill #define	CBRA	1
4*1348Sbill #define	CCHR	2
5*1348Sbill #define	CDOT	4
6*1348Sbill #define	CCL	6
7*1348Sbill #define	NCCL	8
8*1348Sbill #define	CDOL	10
9*1348Sbill #define	CEOF	11
10*1348Sbill #define	CKET	12
11*1348Sbill #define	CBACK	18
12*1348Sbill 
13*1348Sbill #define	CSTAR	01
14*1348Sbill 
15*1348Sbill #define	LBSIZE	512
16*1348Sbill #define	ESIZE	256
17*1348Sbill #define	NBRA	9
18*1348Sbill 
19*1348Sbill char	expbuf[ESIZE];
20*1348Sbill int	circf;
21*1348Sbill char	*braslist[NBRA];
22*1348Sbill char	*braelist[NBRA];
23*1348Sbill char	bittab[] = {
24*1348Sbill 	1,
25*1348Sbill 	2,
26*1348Sbill 	4,
27*1348Sbill 	8,
28*1348Sbill 	16,
29*1348Sbill 	32,
30*1348Sbill 	64,
31*1348Sbill 	128
32*1348Sbill };
33*1348Sbill 
34*1348Sbill dore() {
35*1348Sbill 	register int line;
36*1348Sbill 	register char *p;
37*1348Sbill 
38*1348Sbill 	circf = 0;
39*1348Sbill 	line = fline;
40*1348Sbill 	compile(re);
41*1348Sbill 	do {
42*1348Sbill 		if (redir) fnext();
43*1348Sbill 		else fprev();
44*1348Sbill 		p = fbuf;
45*1348Sbill 		while(*p++ != '\n')
46*1348Sbill 			;
47*1348Sbill 		*--p = '\0';
48*1348Sbill 		if (match(fbuf)) goto l1;
49*1348Sbill 	} while (fline != line);
50*1348Sbill 	error("No match");
51*1348Sbill l1:	*p = '\n';
52*1348Sbill 	fprint();
53*1348Sbill }
54*1348Sbill 
55*1348Sbill 
56*1348Sbill compile(astr)
57*1348Sbill char *astr;
58*1348Sbill {
59*1348Sbill 	register c;
60*1348Sbill 	register char *ep, *sp;
61*1348Sbill 	char *cstart;
62*1348Sbill 	char *lastep;
63*1348Sbill 	int cclcnt;
64*1348Sbill 	char bracket[NBRA], *bracketp;
65*1348Sbill 	int closed;
66*1348Sbill 	char numbra;
67*1348Sbill 	char neg;
68*1348Sbill 
69*1348Sbill 	ep = expbuf;
70*1348Sbill 	sp = astr;
71*1348Sbill 	lastep = 0;
72*1348Sbill 	bracketp = bracket;
73*1348Sbill 	closed = numbra = 0;
74*1348Sbill 	if (*sp == '^') {
75*1348Sbill 		circf++;
76*1348Sbill 		sp++;
77*1348Sbill 	}
78*1348Sbill 	for (;;) {
79*1348Sbill 		if (ep >= &expbuf[ESIZE])
80*1348Sbill 			goto cerror;
81*1348Sbill 		if ((c = *sp++) != '*')
82*1348Sbill 			lastep = ep;
83*1348Sbill 		switch (c) {
84*1348Sbill 
85*1348Sbill 		case '\0':
86*1348Sbill 			*ep++ = CEOF;
87*1348Sbill 			return;
88*1348Sbill 
89*1348Sbill 		case '.':
90*1348Sbill 			*ep++ = CDOT;
91*1348Sbill 			continue;
92*1348Sbill 
93*1348Sbill 		case '*':
94*1348Sbill 			if (lastep==0 || *lastep==CBRA || *lastep==CKET)
95*1348Sbill 				goto defchar;
96*1348Sbill 			*lastep |= CSTAR;
97*1348Sbill 			continue;
98*1348Sbill 
99*1348Sbill 		case '$':
100*1348Sbill 			if (*sp != '\0')
101*1348Sbill 				goto defchar;
102*1348Sbill 			*ep++ = CDOL;
103*1348Sbill 			continue;
104*1348Sbill 
105*1348Sbill 		case '[':
106*1348Sbill 			if(&ep[17] >= &expbuf[ESIZE])
107*1348Sbill 				goto cerror;
108*1348Sbill 			*ep++ = CCL;
109*1348Sbill 			neg = 0;
110*1348Sbill 			if((c = *sp++) == '^') {
111*1348Sbill 				neg = 1;
112*1348Sbill 				c = *sp++;
113*1348Sbill 			}
114*1348Sbill 			cstart = sp;
115*1348Sbill 			do {
116*1348Sbill 				if (c=='\0')
117*1348Sbill 					goto cerror;
118*1348Sbill 				if (c=='-' && sp>cstart && *sp!=']') {
119*1348Sbill 					for (c = sp[-2]; c<*sp; c++)
120*1348Sbill 						ep[c>>3] |= bittab[c&07];
121*1348Sbill 					sp++;
122*1348Sbill 				}
123*1348Sbill 				ep[c>>3] |= bittab[c&07];
124*1348Sbill 			} while((c = *sp++) != ']');
125*1348Sbill 			if(neg) {
126*1348Sbill 				for(cclcnt = 0; cclcnt < 16; cclcnt++)
127*1348Sbill 					ep[cclcnt] ^= -1;
128*1348Sbill 				ep[0] &= 0376;
129*1348Sbill 			}
130*1348Sbill 
131*1348Sbill 			ep += 16;
132*1348Sbill 
133*1348Sbill 			continue;
134*1348Sbill 
135*1348Sbill 		case '\\':
136*1348Sbill 			if((c = *sp++) == '(') {
137*1348Sbill 				if(numbra >= NBRA) {
138*1348Sbill 					goto cerror;
139*1348Sbill 				}
140*1348Sbill 				*bracketp++ = numbra;
141*1348Sbill 				*ep++ = CBRA;
142*1348Sbill 				*ep++ = numbra++;
143*1348Sbill 				continue;
144*1348Sbill 			}
145*1348Sbill 			if(c == ')') {
146*1348Sbill 				if(bracketp <= bracket) {
147*1348Sbill 					goto cerror;
148*1348Sbill 				}
149*1348Sbill 				*ep++ = CKET;
150*1348Sbill 				*ep++ = *--bracketp;
151*1348Sbill 				closed++;
152*1348Sbill 				continue;
153*1348Sbill 			}
154*1348Sbill 
155*1348Sbill 			if(c >= '1' && c <= '9') {
156*1348Sbill 				if((c -= '1') >= closed)
157*1348Sbill 					goto cerror;
158*1348Sbill 				*ep++ = CBACK;
159*1348Sbill 				*ep++ = c;
160*1348Sbill 				continue;
161*1348Sbill 			}
162*1348Sbill 
163*1348Sbill 		defchar:
164*1348Sbill 		default:
165*1348Sbill 			*ep++ = CCHR;
166*1348Sbill 			*ep++ = c;
167*1348Sbill 		}
168*1348Sbill 	}
169*1348Sbill     cerror:
170*1348Sbill 	errexit("RE error\n", (char *)NULL);
171*1348Sbill }
172*1348Sbill 
173*1348Sbill match(p1)
174*1348Sbill register char *p1; {
175*1348Sbill 	register char *p2;
176*1348Sbill 	register c;
177*1348Sbill 		p2 = expbuf;
178*1348Sbill 		if (circf) {
179*1348Sbill 			if (advance(p1, p2))
180*1348Sbill 				goto found;
181*1348Sbill 			goto nfound;
182*1348Sbill 		}
183*1348Sbill 		/* fast check for first character */
184*1348Sbill 		if (*p2==CCHR) {
185*1348Sbill 			c = p2[1];
186*1348Sbill 			do {
187*1348Sbill 				if (*p1!=c)
188*1348Sbill 					continue;
189*1348Sbill 				if (advance(p1, p2))
190*1348Sbill 					goto found;
191*1348Sbill 			} while (*p1++);
192*1348Sbill 			goto nfound;
193*1348Sbill 		}
194*1348Sbill 		/* regular algorithm */
195*1348Sbill 		do {
196*1348Sbill 			if (advance(p1, p2))
197*1348Sbill 				goto found;
198*1348Sbill 		} while (*p1++);
199*1348Sbill 	nfound:
200*1348Sbill 		return(0);
201*1348Sbill 	found:
202*1348Sbill 		return(1);
203*1348Sbill }
204*1348Sbill 
205*1348Sbill advance(lp, ep)
206*1348Sbill register char *lp, *ep;
207*1348Sbill {
208*1348Sbill 	register char *curlp;
209*1348Sbill 	char c;
210*1348Sbill 	char *bbeg;
211*1348Sbill 	int ct;
212*1348Sbill 
213*1348Sbill 	for (;;) switch (*ep++) {
214*1348Sbill 
215*1348Sbill 	case CCHR:
216*1348Sbill 		if (*ep++ == *lp++)
217*1348Sbill 			continue;
218*1348Sbill 		return(0);
219*1348Sbill 
220*1348Sbill 	case CDOT:
221*1348Sbill 		if (*lp++)
222*1348Sbill 			continue;
223*1348Sbill 		return(0);
224*1348Sbill 
225*1348Sbill 	case CDOL:
226*1348Sbill 		if (*lp=='\0')
227*1348Sbill 			continue;
228*1348Sbill 		return(0);
229*1348Sbill 
230*1348Sbill 	case CEOF:
231*1348Sbill 		return(1);
232*1348Sbill 
233*1348Sbill 	case CCL:
234*1348Sbill 		c = *lp++ & 0177;
235*1348Sbill 		if(ep[c>>3] & bittab[c & 07]) {
236*1348Sbill 			ep += 16;
237*1348Sbill 			continue;
238*1348Sbill 		}
239*1348Sbill 		return(0);
240*1348Sbill 	case CBRA:
241*1348Sbill 		braslist[*ep++] = lp;
242*1348Sbill 		continue;
243*1348Sbill 
244*1348Sbill 	case CKET:
245*1348Sbill 		braelist[*ep++] = lp;
246*1348Sbill 		continue;
247*1348Sbill 
248*1348Sbill 	case CBACK:
249*1348Sbill 		bbeg = braslist[*ep];
250*1348Sbill 		if (braelist[*ep]==0)
251*1348Sbill 			return(0);
252*1348Sbill 		ct = braelist[*ep++] - bbeg;
253*1348Sbill 		if(ecmp(bbeg, lp, ct)) {
254*1348Sbill 			lp += ct;
255*1348Sbill 			continue;
256*1348Sbill 		}
257*1348Sbill 		return(0);
258*1348Sbill 
259*1348Sbill 	case CBACK|CSTAR:
260*1348Sbill 		bbeg = braslist[*ep];
261*1348Sbill 		if (braelist[*ep]==0)
262*1348Sbill 			return(0);
263*1348Sbill 		ct = braelist[*ep++] - bbeg;
264*1348Sbill 		curlp = lp;
265*1348Sbill 		while(ecmp(bbeg, lp, ct))
266*1348Sbill 			lp += ct;
267*1348Sbill 		while(lp >= curlp) {
268*1348Sbill 			if(advance(lp, ep))	return(1);
269*1348Sbill 			lp -= ct;
270*1348Sbill 		}
271*1348Sbill 		return(0);
272*1348Sbill 
273*1348Sbill 
274*1348Sbill 	case CDOT|CSTAR:
275*1348Sbill 		curlp = lp;
276*1348Sbill 		while (*lp++);
277*1348Sbill 		goto star;
278*1348Sbill 
279*1348Sbill 	case CCHR|CSTAR:
280*1348Sbill 		curlp = lp;
281*1348Sbill 		while (*lp++ == *ep);
282*1348Sbill 		ep++;
283*1348Sbill 		goto star;
284*1348Sbill 
285*1348Sbill 	case CCL|CSTAR:
286*1348Sbill 		curlp = lp;
287*1348Sbill 		do {
288*1348Sbill 			c = *lp++ & 0177;
289*1348Sbill 		} while(ep[c>>3] & bittab[c & 07]);
290*1348Sbill 		ep += 16;
291*1348Sbill 		goto star;
292*1348Sbill 
293*1348Sbill 	star:
294*1348Sbill 		if(--lp == curlp) {
295*1348Sbill 			continue;
296*1348Sbill 		}
297*1348Sbill 
298*1348Sbill 		if(*ep == CCHR) {
299*1348Sbill 			c = ep[1];
300*1348Sbill 			do {
301*1348Sbill 				if(*lp != c)
302*1348Sbill 					continue;
303*1348Sbill 				if(advance(lp, ep))
304*1348Sbill 					return(1);
305*1348Sbill 			} while(lp-- > curlp);
306*1348Sbill 			return(0);
307*1348Sbill 		}
308*1348Sbill 
309*1348Sbill 		do {
310*1348Sbill 			if (advance(lp, ep))
311*1348Sbill 				return(1);
312*1348Sbill 		} while (lp-- > curlp);
313*1348Sbill 		return(0);
314*1348Sbill 
315*1348Sbill 	default:
316*1348Sbill 		errexit("RE botch\n", (char *)NULL);
317*1348Sbill 	}
318*1348Sbill }
319*1348Sbill ecmp(a, b, count)
320*1348Sbill char	*a, *b;
321*1348Sbill {
322*1348Sbill 	register cc = count;
323*1348Sbill 	while(cc--)
324*1348Sbill 		if(*a++ != *b++)	return(0);
325*1348Sbill 	return(1);
326*1348Sbill }
327*1348Sbill 
328*1348Sbill 
329*1348Sbill errexit(s)
330*1348Sbill char *s; {
331*1348Sbill 	error(s);
332*1348Sbill 	return;
333*1348Sbill }
334