|
|
1.1 root 1: /*% cc -c -O %
2: */
3: #include "vars.h"
4: #define ESIZE 128 /* ESIZE-1 must fit in a signed byte */
5: char expbuf[ESIZE+4];
6: int expgood /*0*/; /* flag indicating if compiled exp is good */
7: #define CCHR 2
8: #define CDOT 4
9: #define CCL 6
10: #define NCCL 8
11: #define CFUNNY 10
12: #define CALT 12
13: #define CBACK 14
14:
15: #define STAR 01
16: #define STARABLE CBACK
17:
18: #define CKET 16
19: #define CDOL 17
20: #define CEOF 18
21: #define CBRA 19
22: #define CBOI 20
23: #define CEOI 21
24: #define CSPACE 22
25: int circfl;
26: char pmagic[] = "/.$^*+\\()<|>{}[!_123456789";
27: compile(eof)
28: char eof;
29: {
30: register c;
31: register char *ep, *penultep;
32: char *lastep, *bracketp, bracket[NBRA];
33: int getsvc();
34: int getchar();
35: struct{
36: char *althd; /* start of code for < ... > */
37: char *altlast; /* start of code for last < or | */
38: char *bpstart; /* bracketp at start of < and | */
39: char *bpend; /* bracketp at end of > or | */
40: int nbstart; /* nbra at start of < and | */
41: int nbend; /* nbra at end of > or | */
42: int firstalt; /* is this the first alternative? */
43: } *asp, altstk[NBRA];
44:
45: if(eof == '\n')
46: error('x');
47: pmagic[0] = eof;
48: if ((c=nextchar()) == eof || c=='\n') {
49: if (!expgood)
50: goto cerror;
51: if(c!='\n')
52: getchar(); /* eat the eof character */
53: return;
54: }
55: expgood = FALSE;
56: ep = expbuf;
57: lastep = 0;
58: bracketp = bracket;
59: nbra = 0;
60: asp = &altstk[-1];
61: startstring(); /* for the saved pattern register */
62: circfl = 0;
63: if (c=='^') {
64: getsvc(); /* save the caret */
65: circfl++;
66: }
67: for (;;) {
68: c = getquote(pmagic, getsvc);
69: if (c==eof || c=='\n') {
70: if (bracketp!=bracket || asp>=altstk)
71: goto cerror;
72: *ep++ = CEOF;
73: expgood = TRUE;
74: dropstring(); /* lose the eof character */
75: setstring(SAVPAT);
76: if(c=='\n')
77: ungetchar(c);
78: return;
79: }
80: if (ep >= &expbuf[ESIZE-5])
81: goto cerror;
82: penultep = lastep;
83: lastep = ep;
84:
85: if(c != (eof|0200)) switch (c) {
86: case '('|0200:
87: if (nbra >= NBRA)
88: goto cerror;
89: *bracketp++ = nbra;
90: *ep++ = CBRA;
91: *ep++ = nbra++;
92: continue;
93: case ')'|0200:
94: if (bracketp <= bracket)
95: goto cerror;
96: *ep++ = CKET;
97: *ep++ = *--bracketp;
98: continue;
99: case '{'|0200:
100: *ep++ = CBOI;
101: continue;
102: case '}'|0200:
103: *ep++ = CEOI;
104: continue;
105: case '_'|0200:
106: *ep++ = CSPACE;
107: continue;
108: case '!'|0200:
109: *ep++ = CFUNNY;
110: continue;
111: case '<':
112: if (++asp >= &altstk[NBRA])
113: goto cerror;
114: *ep++ = CALT;
115: asp->althd = ep;
116: ep++;
117: asp->bpstart = bracketp;
118: asp->nbstart = nbra;
119: asp->firstalt = TRUE;
120: asp->altlast = ep++;
121: lastep = 0;
122: continue;
123: case '|':
124: if (asp<altstk)
125: break;
126: if (asp->firstalt) {
127: asp->bpend = bracketp;
128: asp->nbend = nbra;
129: }
130: if (bracketp!=asp->bpend || nbra!=asp->nbend)
131: goto cerror;
132: *ep++ = CEOF;
133: asp->altlast[0] = ep-asp->altlast;
134: asp->firstalt = FALSE;
135: bracketp = asp->bpstart;
136: nbra = asp->nbstart;
137: asp->altlast = ep++;
138: lastep = 0;
139: continue;
140: case '>':
141: if (asp<altstk)
142: break;
143: if (!asp->firstalt &&
144: (bracketp!=asp->bpend || nbra!=asp->nbend))
145: goto cerror;
146: *ep++ = CEOF;
147: asp->altlast[0] = ep-asp->altlast;
148: lastep = asp->althd;
149: *lastep = ep-lastep;
150: lastep--;
151: if (bracketp!=asp->bpstart || nbra!=asp->nbstart)
152: lastep = 0;
153: asp--;
154: continue;
155: case '*':
156: case '+':
157: if (penultep==0){
158: *ep++ = CCHR;
159: *ep++ = c;
160: } else {
161: if(*penultep>STARABLE)
162: goto cerror;
163: if(c == '+'){
164: if((ep-penultep)+ep >= &expbuf[ESIZE-1])
165: goto cerror;
166: do
167: *ep++ = *penultep++;
168: while (penultep!=lastep);
169: }
170: *penultep |= STAR;
171: lastep = 0;
172: }
173: continue;
174: case '.':
175: *ep++ = CDOT;
176: continue;
177:
178: case '[':
179: penultep = ep;
180: *ep++ = CCL;
181: *ep++ = 0;
182: if ((c=getsvc()) == '^') {
183: c = getsvc();
184: ep[-2] = NCCL;
185: }
186: do {
187: if (c == EOF || c == '\n')
188: goto cerror;
189: *ep++ = c;
190: if ((lastc=getsvc()) == '-') {
191: c=getsvc();
192: if (c == EOF || c == '\n' || c<=ep[-1])
193: goto cerror;
194: ep[-1] |= 0200;
195: *ep++ = c;
196: lastc = getsvc(); /* prime lastc */
197: } else if (dflag&&'a'<=(c|' ')&&(c|' ')<='z')
198: *ep++ = c^' ';
199: if (ep >= &expbuf[ESIZE-1])
200: goto cerror;
201: } while ((c=lastc) != ']');
202: penultep[1] = ep-penultep-1;
203: continue;
204:
205:
206: case '$':
207: if (nextchar() == eof || peekc=='\n') {
208: *ep++ = CDOL;
209: continue;
210: }
211: /* fall through */
212: default:
213: break;
214: }
215: /* if fell through switch, match literal character */
216: /* Goddamned sign extension! */
217: if ((c&0200) && (c&0177)>='1' && (c&0177)<='9') {
218: *ep++ = CBACK;
219: *ep++ = c-('1'|0200);
220: continue;
221: }
222: c &= ~0200;
223: if(dflag && c|' '>='a' && c|' '<='z'){
224: *ep++ = CCL;
225: *ep++ = 3;
226: *ep++ = c;
227: *ep++ = c^' ';
228: }
229: else{
230: *ep++ = CCHR;
231: *ep++ = c;
232: }
233: }
234: cerror:
235: error('p');
236: }
237: getsvc(){
238: register c;
239: addstring(c=getchar());
240: return(c);
241: }
242: int
243: execute(addr)
244: int *addr;
245: {
246: register char *p1, *p2;
247:
248: if (addr==0) {
249: if((p1=loc2) == 0) /* G command */
250: p1 = linebuf;
251: else if (circfl) /* not first search in substitute */
252: return(FALSE);
253: } else {
254: if (addr==zero)
255: return(FALSE);
256: p1 = getline(*addr, linebuf);
257: }
258: p2 = expbuf;
259: if (circfl) {
260: loc1 = p1;
261: return(advance(p1, p2));
262: }
263: do {
264: if (*p2 != CCHR || p2[1] == *p1) {
265: if (advance(p1, p2)) {
266: loc1 = p1;
267: return(TRUE);
268: }
269: }
270: } while (*p1++);
271: return(FALSE);
272: }
273:
274: int
275: advance(lp, ep)
276: register char *lp, *ep;
277: {
278: register char *curlp;
279: char *althd, *altend;
280:
281: for (;;) {
282: curlp = lp;
283: switch (*ep++) {
284:
285: case CCHR:
286: if (*ep++ == *lp++)
287: continue;
288: return(FALSE);
289:
290: case CCHR|STAR:
291: do ; while (*lp++ == *ep);
292: ep++;
293: break;
294:
295: case CDOT:
296: if (*lp++)
297: continue;
298: return(FALSE);
299:
300: case CDOT|STAR:
301: do ; while (*lp++);
302: break;
303:
304: case CCL:
305: case NCCL:
306: if (cclass(ep, *lp++, ep[-1]==CCL)) {
307: ep += *ep;
308: continue;
309: }
310: return(FALSE);
311:
312: case CCL|STAR:
313: case NCCL|STAR:
314: do ; while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
315: ep += *ep;
316: break;
317:
318: case CFUNNY:
319: if (*lp>=' ' && *lp!='\177' || *lp=='\t' || *lp=='\0')
320: return(FALSE);
321: lp++;
322: continue;
323:
324: case CFUNNY|STAR:
325: while (*lp<' ' && *lp && *lp!='\t' || *lp=='\177')
326: lp++;
327: lp++;
328: break;
329:
330: case CBACK:
331: if (braelist[*ep]==0)
332: error('p');
333: if (backref(*ep++, lp)) {
334: lp += braelist[ep[-1]] - braslist[ep[-1]];
335: continue;
336: }
337: return(FALSE);
338:
339: case CBACK|STAR:
340: if (braelist[*ep] == 0)
341: error('p');
342: curlp = lp;
343: while (backref(*ep, lp))
344: lp += braelist[*ep] - braslist[*ep];
345: while (lp >= curlp) {
346: if (advance(lp, ep+1))
347: return(TRUE);
348: lp -= braelist[*ep] - braslist[*ep];
349: }
350: ep++;
351: continue;
352:
353: case CBRA:
354: braslist[*ep++] = lp;
355: continue;
356:
357: case CKET:
358: braelist[*ep++] = lp;
359: continue;
360:
361: case CDOL:
362: if (*lp==0)
363: continue;
364: return(FALSE);
365:
366: case CEOF:
367: loc2 = lp;
368: return(TRUE);
369:
370: case CBOI:
371: if (alfmatch(*lp,0)
372: && (lp==linebuf || !alfmatch(lp[-1],1)))
373: continue;
374: return(FALSE);
375:
376: case CEOI:
377: if (!alfmatch(*lp,1)
378: && lp!=linebuf && alfmatch(lp[-1],1))
379: continue;
380: return(FALSE);
381:
382: case CSPACE:
383: if (*lp==' ' || *lp=='\t') {
384: while (*lp == ' ' || *lp=='\t')
385: lp++;
386: continue;
387: }
388: return(FALSE);
389:
390: case CALT:
391: althd = ep-1;
392: altend = ep + *ep;
393: for(ep++; ; ep+= *ep) {
394: if(ep == altend)
395: return(FALSE);
396: if(advance(lp,ep+1) && advance(loc2,altend))
397: return(TRUE);
398: }
399:
400: case CALT|STAR:
401: althd = ep-1;
402: altend = ep + *ep;
403: for(ep++; ep!=altend; ep+= *ep){
404: if(advance(lp, ep+1)){
405: if(loc2 == lp)
406: break;
407: if(advance(loc2, althd))
408: return(TRUE);
409: }
410: }
411: /* return (advance(lp,altend)) */
412: continue;
413:
414: default:
415: error('!');
416: }
417: /* star logic: executed by falling out of switch */
418: do {
419: lp--;
420: if (advance(lp, ep))
421: return(TRUE);
422: } while (lp > curlp);
423: return(FALSE);
424: }
425: }
426:
427: backref(i, lp)
428: register i;
429: register char *lp;
430: {
431: register char *bp;
432:
433: bp = braslist[i];
434: while (*bp++ == *lp++)
435: if (bp >= braelist[i])
436: return(TRUE);
437: return(FALSE);
438: }
439: int alfmatch(c,tail)
440: register char c;
441: {
442: return (('a' <= c && c <= 'z') ||
443: ('A' <= c && c <= 'Z') ||
444: (c == '_') ||
445: (tail && '0' <= c && c<= '9'));
446: }
447:
448:
449: cclass(set, c, f)
450: register char *set;
451: register c;
452: {
453: register n;
454: if (c == 0)
455: return(0);
456: n = *set++;
457: while (--n) {
458: if (*set&0200) {
459: if ((*set++ & 0177) <= c) {
460: if (c <= *set++)
461: return(f);
462: } else
463: set++;
464: --n;
465: } else if (*set++ == c)
466: return(f);
467: }
468: return(!f);
469: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.