|
|
1.1 root 1: #include "emacs_gb.h"
2: #include "emacs_io.h"
3:
4:
5: /* EMACS_MODES: c !fill */
6:
7: #define GETC() (*sp++)
8: #define PEEKC() (*sp)
9: #define UNGETC(c) (--sp)
10: #define RETURN(c) return(NULL);
11: #define ERROR(c) return(c);
12:
13: extern char casem[];
14: extern char bits[];
15:
16: #define RESIZE 256
17:
18: /* basic comparison types */
19:
20: #define CCHR 1 /* single char */
21: #define CDOT 2 /* any char */
22: #define CCL 3 /* multiple guess */
23: #define CBLST 4 /* last expression */
24: #define CDOL 5 /* $ */
25: #define CEOF 6 /* end of line */
26:
27: /* markers */
28:
29: #define CBRA 8 /* \( marker */
30: #define CKET 9 /* \) marker */
31: #define CBWD 10 /* start of word */
32: #define CEWD 11 /* end of word */
33:
34: /* modifiers */
35:
36: #define BASTYP 15 /* mask for base type */
37:
38: #define RNGE 16 /* range of types */
39:
40: #define NBRA 9
41:
42: #define PLACE(c) ep[c >> 3] ^= bittab[c & 07]
43: #define ISTHERE(c) (ep[c >> 3] & bittab[c & 07])
44:
45: char *braslist[NBRA];
46: char *braelist[NBRA];
47: int nbra, ebra;
48: char *loc1;
49: int closed;
50: int loc2;
51:
52: int low;
53: int size;
54:
55: char bittab[] = {
56: 1,
57: 2,
58: 4,
59: 8,
60: 16,
61: 32,
62: 64,
63: 128
64: };
65:
66: int
67: compile(sp, ep)
68: register char *ep;
69: register char *sp;
70:
71: /* Keywords: regular-expressions searching parsing */
72: {
73: register int c;
74: char *endbuf;
75: char *lastep = sp;
76: char bracket[NBRA], *bracketp;
77: char neg;
78: int lc;
79: int i, cflg;
80:
81: lastep = NULL;
82: bracketp = bracket;
83: closed = nbra = ebra = 0;
84:
85: endbuf = ep + RESIZE;
86:
87: for (;;) {
88: if (ep >= endbuf)
89: ERROR(62);
90: if((c = GETC()) != '*' && (c != '+') &&
91: ((c != '\\') || (PEEKC() != '{')))
92: lastep = ep;
93: if (c == 0) {
94: *ep++ = CEOF;
95: RETURN(ep);
96: }
97: switch (c) {
98:
99: case '.':
100: *ep++ = CDOT;
101: continue;
102:
103: case '\n':
104: ERROR(55);
105: case '*':
106: if (lastep==0 || *lastep==CBRA || *lastep==CKET)
107: goto defchar;
108: *lastep |= RNGE;
109: *ep++=0;
110: *ep++=255;
111: continue;
112: case '+':
113: if (lastep==0 )
114: goto defchar;
115: *lastep |= RNGE;
116: *ep++ = 1;
117: *ep++ = 255;
118: continue;
119:
120: case '$':
121: if(PEEKC() != 0)
122: goto defchar;
123: *ep++ = CDOL;
124: continue;
125:
126: case '[':
127: if(&ep[17] >= endbuf)
128: ERROR(62);
129:
130: *ep++ = CCL;
131: lc = 0;
132: if((c = GETC()) == '^') {
133: neg = -1;
134: c = GETC();
135: } else neg = 0;
136: for(i = 0; i < 16; i++)
137: ep[i] = neg;
138:
139:
140: do {
141: if(c == '\0')
142: ERROR(61);
143: if(c == '-' && (lc != 0) && (PEEKC() != ']')) {
144: c = GETC();
145: } else lc = c;
146: while(lc <= c) {
147: PLACE(lc);
148: lc++;
149: }
150: } while((c = GETC()) != ']');
151: ep[1] &= 0373; /* make sure that newline is not matched */
152: ep += 16;
153: continue;
154:
155: case '\\':
156: switch(c = GETC()) {
157:
158: case '(':
159: if(nbra >= NBRA)
160: ERROR(57);
161: *bracketp++ = nbra;
162: *ep++ = CBRA;
163: *ep++ = nbra++;
164: continue;
165:
166: case ')':
167: if(bracketp <= bracket || ++ebra != nbra)
168: ERROR(56);
169: *ep++ = CKET;
170: *ep++ = *--bracketp;
171: closed++;
172: continue;
173:
174: case '<':
175: *ep++ = CBWD;
176: continue;
177: case '>':
178: *ep++ = CEWD;
179: continue;
180:
181: case '{':
182: if(lastep == (char *) (0))
183: goto defchar;
184: *lastep |= RNGE;
185: cflg = 0;
186: nlim:
187: c = GETC();
188: if (c == '\\') {
189: i = 255; /* infinity */
190: } else {
191: i = 0;
192: while('0' <= c && c <= '9') {
193: i = 10 * i + (c - '0');
194: c = GETC();
195: }
196: }
197: if (i > 255) ERROR(52);
198: *ep++ = i;
199: if (c == ',') {
200: if(cflg++) ERROR(58);
201: goto nlim; /* get 2'nd number */
202: }
203: if((c != '\\') || (GETC() != '}')) ERROR(59);
204: if(!cflg) /* one number */
205: *ep++ = i;
206: else if((ep[-1] & 0377) < (ep[-2] & 0377))
207: ERROR(60);
208: continue;
209:
210: case '\n':
211: ERROR(55);
212:
213: case 'n':
214: c = '\n';
215: goto defchar;
216:
217: default:
218: if(c >= '1' && c <= '9') {
219: if((c -= '1') >= closed)
220: ERROR(54);
221: *ep++ = CBLST;
222: *ep++ = c;
223: continue;
224: }
225: }
226: /* Drop through to default to use \ to turn off special chars */
227:
228: defchar:
229: default:
230: lastep = ep;
231: *ep++ = CCHR;
232: *ep++ = c;
233: }
234: }
235: }
236:
237:
238: advance(lp, ep)
239: register char *lp, *ep;
240:
241: /* Keywords: regular-expressions searching star-processing:10 */
242:
243: {
244: register char *curlp;
245: char c;
246: int typ;
247: char *bbeg;
248: int ct;
249:
250: for (;;) switch (typ = *ep++) {
251:
252: case CCHR:
253: if (*ep++ == casem[(*lp++)&0177])
254: continue;
255: return(0);
256:
257: case CDOT:
258: if (*lp++ != EOL)
259: continue;
260: return(0);
261:
262: case CBWD:
263: if (bits[lp[-1]] & 01) continue;
264: return(0);
265: case CEWD:
266: if (bits[*lp] & 01) continue;
267: return(0);
268: case CDOL:
269: if (*lp==EOL) {
270: continue;
271: }
272: return(0);
273:
274: case CEOF:
275: loc2 = lp-klptr;
276: return(1);
277:
278: case CCL:
279: c = casem[*lp++ & 0177];
280: if(ISTHERE(c)) {
281: ep += 16;
282: continue;
283: }
284: return(0);
285: case CBRA:
286: braslist[*ep++] = lp;
287: continue;
288:
289: case CKET:
290: braelist[*ep++] = lp;
291: continue;
292:
293: case CCHR|RNGE:
294: c = *ep++;
295: getrnge(ep);
296: grnge: ct = 0;
297: curlp = lp;
298: while(ct < size) {
299: switch(typ&BASTYP) {
300:
301: case CCHR: if(casem[(*lp++)&0177] != c) goto broke;
302: break;
303: case CDOT: if (*lp++ == EOL) goto broke;
304: break;
305: case CCL: c = casem[(*lp++)&0177];
306: if(!ISTHERE(c)) goto broke;
307: break;
308: }
309: if (++ct == low) curlp = lp;
310: }
311: broke: if (ct < low) return(0); /* too few */
312:
313: if (size == ct) lp++; /* didn't do last compare */
314: if ((typ&BASTYP) == CCL) ep += 16;
315: ep += 2;
316:
317: while (lp > curlp) {
318: if (advance(--lp, ep)) return(1);
319: }
320: return(0);
321: case CDOT|RNGE:
322: getrnge(ep);
323: goto grnge;
324: case CCL|RNGE:
325: getrnge(ep + 16);
326: goto grnge;
327: case CBLST:
328: bbeg = braslist[*ep];
329: ct = braelist[*ep++] - bbeg;
330:
331: if(ecmp(bbeg, lp, ct)) {
332: lp += ct;
333: continue;
334: }
335: return(0);
336:
337: case CBLST|RNGE:
338: bbeg = braslist[*ep];
339: ct = braelist[*ep++] - bbeg;
340: ep+=2;
341: curlp = lp;
342: while(ecmp(bbeg, lp, ct))
343: lp += ct;
344:
345: while(lp >= curlp) {
346: if(advance(lp, ep)) return(1);
347: lp -= ct;
348: }
349: return(0);
350: }
351: }
352:
353: getrnge(str)
354: register char *str;
355: /* Keywords: regular-expressions searching:20 star-processing */
356:
357: {
358: low = *str++ & 0377;
359: size = *str&0377;
360: if (size == 255) size = 2000;
361: }
362:
363: ecmp(a, b, count)
364: register char *a, *b;
365: register int count;
366:
367: /* Keywords: star-processing regular-expressions searching:10 */
368:
369: {
370: while(count--)
371: if(*a++ != *b++) return(0);
372: return(1);
373: }
374:
375:
376:
377: rsrch(arg)
378:
379: /* Keywords: searching regular-expressions commands key-bindings:10 */
380:
381: int arg;
382: {
383: register int dir;
384: extern char presst[];
385: register char *xp;
386: register char c;
387: int ol,oc;
388: int x,y;
389:
390: if (arg < 0) {
391: dir = -1;
392: arg = -arg;
393: } else {
394: dir = 1;
395: }
396: ol = curln;
397: oc = column;
398: if (xp = getname("expr: ")) { /* get expression */
399: if (*xp == 0) xp = presst; /* last string */
400: prompt1("expr: %s",xp);
401: while(rgsrch(curln,column,xp,(arg == 1),dir)) {
402: move(kline,kcol);
403: ol = curln;
404: oc = column;
405: strcpy(presst,xp);
406: if (infrn == 0) {
407: disup();
408: x = mline;
409: y = mcol;
410: prompt1("expr: %s",xp);
411: mgo(x,y);
412: c = getchar();
413: } else return(1);
414:
415: if (x=issrch(c)) {
416: dir=x;
417: forw(dir);
418: } else {
419: unprompt();
420: ungetch(c);
421: return(1);
422: }
423: }
424: prompt1("Search failed");
425: move(ol,oc);
426: if (infrn >=0) beep();
427: }
428: return(0);
429: }
430:
431: /* rgsrch -- regular expression search */
432:
433: rgsrch(froml,fromc,cp,wrap,dir)
434: int froml;
435: int fromc;
436: int wrap;
437: register int dir;
438: char *cp;
439:
440: /* Keywords: regular-expressions searching query-replace:20 */
441:
442: {
443: register int en;
444: char rebuf[RESIZE];
445: register int beg;
446: char *lp;
447:
448: lp = cp;
449: while (beg = *lp) *lp++ = casem[beg&0177]; /* map string to allowed case */
450: if (*cp == '^') {
451: cp++;
452: beg = 1;
453: } else beg = 0;
454: if (en = compile(cp,rebuf)) { /* if format error */
455: error(WARN,en);
456: return(0);
457: }
458: kline = froml;
459: kcol = fromc;
460:
461: while (1) {
462: if (brkflg) brkit();
463: klptr = mkline(kline);
464: if (beg) {
465: if ((kcol == 0) || (dir<0)) {
466: kcol = 0;
467: if(advance(klptr,rebuf)) {
468: loc1 = klptr+kcol;
469: return(1);
470: }
471: }
472: } else {
473: while (1) {
474: if ((rebuf[0] != CCHR) || (rebuf[1] == casem[klptr[kcol]&0177])) {
475:
476: if (advance(klptr+kcol, rebuf)) {
477:
478: /* The following line rejects an attempt to match the last newline in the buffer */
479: if ((kline == nlines) && klptr[kcol] == EOL) goto nomatch;
480: loc1 = klptr+kcol;
481: return(1);
482: }
483: }
484: if (dir>0) {
485: if (klptr[kcol] == EOL) goto nomatch;
486: else kcol++;
487: } else {
488: if (kcol == 0) goto nomatch;
489: else kcol--;
490: }
491: if ((kline == froml) && (kcol == fromc)) return(0);
492: }
493: }
494: nomatch: kline += dir;
495: if (wrap) {
496: if (kline > nlines) kline = 1;
497: if (kline < 1) kline = nlines;
498:
499: } else {
500: if ((kline > nlines) || (kline <1)) return(0);
501: }
502: if (beg || (dir>0)) kcol = 0;
503: else kcol = leng(kline);
504: if (wrap && (kline == froml) && (kcol == fromc)) return(0);
505: if (beg && (kline == froml)) return(0);
506: }
507: }
508:
509: /* regrep -- replace sub expression */
510: /* assumes last deleted text is in the kill stack, pointers set up */
511:
512: regrep(i)
513:
514: register int i;
515:
516: /* Keywords: query-replace commands regular-expressions */
517:
518:
519: {
520: register int x;
521: register int y;
522:
523: if (i <= closed) {
524: yank(1); /* bring back everything */
525: y = braslist[i]-loc1; /* length to kill */
526: back(y); /* adjust mark position correctly */
527:
528: exch(1); /* back to beggining */
529: fdel(y); /* kill first part */
530: kpop();
531: forw(braelist[i]-braslist[i]);
532: mkill(1); /* now kill the rest */
533: kpop();
534: unpop(3); /* Remove from the undo stack */
535: return(1);
536: } else return(0);
537: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.