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