|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)ed.c 4.13.1.1 (Berkeley) 10/21/90";
3: #endif
4:
5: /*
6: * Editor
7: */
8: #include <sys/param.h>
9: #include <sys/signal.h>
10: #include <sgtty.h>
11: #undef CEOF
12: #include <setjmp.h>
13: #include "pathnames.h"
14:
15: #define NULL 0
16: #define LBSIZE 512
17: #define ESIZE 128
18: #define GBSIZE 256
19: #define NBRA 5
20: #define EOF -1
21:
22: #define CBRA 1
23: #define CCHR 2
24: #define CDOT 4
25: #define CCL 6
26: #define NCCL 8
27: #define CDOL 10
28: #define CEOF 11
29: #define CKET 12
30: #define CBACK 14
31:
32: #define STAR 01
33:
34: char Q[] = "";
35: char T[] = "TMP";
36: #define READ 0
37: #define WRITE 1
38:
39: int peekc;
40: int lastc;
41: char savedfile[MAXPATHLEN];
42: char file[MAXPATHLEN];
43: char linebuf[LBSIZE];
44: char rhsbuf[LBSIZE/2];
45: char expbuf[ESIZE+4];
46: int circfl;
47: int *zero;
48: int *dot;
49: int *dol;
50: int *addr1;
51: int *addr2;
52: char genbuf[LBSIZE];
53: long count;
54: char *nextip;
55: char *linebp;
56: int ninbuf;
57: int io;
58: int pflag;
59: long lseek();
60: sig_t oldhup;
61: sig_t oldquit;
62: int vflag = 1;
63:
64:
65: int listf;
66: int col;
67: char *globp;
68: int tfile = -1;
69: int tline;
70: char tfname[sizeof(_PATH_TMP) + 20];
71: char *loc1;
72: char *loc2;
73: char *locs;
74: char ibuff[512];
75: int iblock = -1;
76: char obuff[512];
77: int oblock = -1;
78: int ichanged;
79: int nleft;
80: char WRERR[] = "WRITE ERROR";
81: int names[26];
82: int anymarks;
83: char *braslist[NBRA];
84: char *braelist[NBRA];
85: int nbra;
86: int subnewa;
87: int subolda;
88: int fchange;
89: int wrapp;
90: unsigned nlall = 128;
91:
92: int *address();
93: char *getline();
94: char *getblock();
95: char *place();
96: char *mktemp();
97: char *malloc();
98: char *realloc();
99: jmp_buf savej;
100:
101: main(argc, argv)
102: char **argv;
103: {
104: register char *p1, *p2;
105: extern void onintr(), quit(), onhup();
106: sig_t oldintr;
107:
108: oldquit = signal(SIGQUIT, SIG_IGN);
109: oldhup = signal(SIGHUP, SIG_IGN);
110: oldintr = signal(SIGINT, SIG_IGN);
111: if ((int)signal(SIGTERM, SIG_IGN) == 0)
112: signal(SIGTERM, quit);
113: argv++;
114: while (argc > 1 && **argv=='-') {
115: switch((*argv)[1]) {
116:
117: case '\0':
118: vflag = 0;
119: break;
120:
121: case 'q':
122: signal(SIGQUIT, SIG_DFL);
123: vflag = 1;
124: break;
125:
126: }
127: argv++;
128: argc--;
129: }
130:
131: if (argc>1) {
132: p1 = *argv;
133: p2 = savedfile;
134: while (*p2++ = *p1++)
135: ;
136: globp = "r";
137: }
138: zero = (int *)malloc(nlall*sizeof(int));
139: (void)strcpy(tfname, _PATH_TMP);
140: (void)strcat(tfname, "_edXXXXXX");
141: (void)mktemp(tfname);
142: init();
143: if (((int)oldintr&01) == 0)
144: signal(SIGINT, onintr);
145: if (((int)oldhup&01) == 0)
146: signal(SIGHUP, onhup);
147: setjmp(savej);
148: commands();
149: quit();
150: }
151:
152: commands()
153: {
154: int getfile(), gettty();
155: register *a1, c;
156:
157: for (;;) {
158: if (pflag) {
159: pflag = 0;
160: addr1 = addr2 = dot;
161: goto print;
162: }
163: addr1 = 0;
164: addr2 = 0;
165: do {
166: addr1 = addr2;
167: if ((a1 = address())==0) {
168: c = getchr();
169: break;
170: }
171: addr2 = a1;
172: if ((c=getchr()) == ';') {
173: c = ',';
174: dot = a1;
175: }
176: } while (c==',');
177: if (addr1==0)
178: addr1 = addr2;
179: switch(c) {
180:
181: case 'a':
182: setdot();
183: newline();
184: append(gettty, addr2);
185: continue;
186:
187: case 'c':
188: delete();
189: append(gettty, addr1-1);
190: continue;
191:
192: case 'd':
193: delete();
194: continue;
195:
196: case 'E':
197: fchange = 0;
198: c = 'e';
199: case 'e':
200: setnoaddr();
201: if (vflag && fchange) {
202: fchange = 0;
203: error(Q);
204: }
205: filename(c);
206: init();
207: addr2 = zero;
208: goto caseread;
209:
210: case 'f':
211: setnoaddr();
212: filename(c);
213: puts(savedfile);
214: continue;
215:
216: case 'g':
217: global(1);
218: continue;
219:
220: case 'i':
221: setdot();
222: nonzero();
223: newline();
224: append(gettty, addr2-1);
225: continue;
226:
227:
228: case 'j':
229: if (addr2==0) {
230: addr1 = dot;
231: addr2 = dot+1;
232: }
233: setdot();
234: newline();
235: nonzero();
236: join();
237: continue;
238:
239: case 'k':
240: if ((c = getchr()) < 'a' || c > 'z')
241: error(Q);
242: newline();
243: setdot();
244: nonzero();
245: names[c-'a'] = *addr2 & ~01;
246: anymarks |= 01;
247: continue;
248:
249: case 'm':
250: move(0);
251: continue;
252:
253: case '\n':
254: if (addr2==0)
255: addr2 = dot+1;
256: addr1 = addr2;
257: goto print;
258:
259: case 'l':
260: listf++;
261: case 'p':
262: case 'P':
263: newline();
264: print:
265: setdot();
266: nonzero();
267: a1 = addr1;
268: do {
269: puts(getline(*a1++));
270: } while (a1 <= addr2);
271: dot = addr2;
272: listf = 0;
273: continue;
274:
275: case 'Q':
276: fchange = 0;
277: case 'q':
278: setnoaddr();
279: newline();
280: quit();
281:
282: case 'r':
283: filename(c);
284: caseread:
285: if ((io = open(file, 0)) < 0) {
286: lastc = '\n';
287: error(file);
288: }
289: setall();
290: ninbuf = 0;
291: c = zero != dol;
292: append(getfile, addr2);
293: exfile();
294: fchange = c;
295: continue;
296:
297: case 's':
298: setdot();
299: nonzero();
300: substitute(globp!=0);
301: continue;
302:
303: case 't':
304: move(1);
305: continue;
306:
307: case 'u':
308: setdot();
309: nonzero();
310: newline();
311: if ((*addr2&~01) != subnewa)
312: error(Q);
313: *addr2 = subolda;
314: dot = addr2;
315: continue;
316:
317: case 'v':
318: global(0);
319: continue;
320:
321: case 'W':
322: wrapp++;
323: case 'w':
324: setall();
325: nonzero();
326: filename(c);
327: if(!wrapp ||
328: ((io = open(file,1)) == -1) ||
329: ((lseek(io, 0L, 2)) == -1))
330: if ((io = creat(file, 0666)) < 0)
331: error(file);
332: wrapp = 0;
333: putfile();
334: exfile();
335: if (addr1==zero+1 && addr2==dol)
336: fchange = 0;
337: continue;
338:
339:
340:
341: case '=':
342: setall();
343: newline();
344: count = (addr2-zero)&077777;
345: putd();
346: putchr('\n');
347: continue;
348:
349: case '!':
350: callunix();
351: continue;
352:
353: case EOF:
354: return;
355:
356: }
357: error(Q);
358: }
359: }
360:
361: int *
362: address()
363: {
364: register *a1, minus, c;
365: int n, relerr;
366:
367: minus = 0;
368: a1 = 0;
369: for (;;) {
370: c = getchr();
371: if ('0'<=c && c<='9') {
372: n = 0;
373: do {
374: n *= 10;
375: n += c - '0';
376: } while ((c = getchr())>='0' && c<='9');
377: peekc = c;
378: if (a1==0)
379: a1 = zero;
380: if (minus<0)
381: n = -n;
382: a1 += n;
383: minus = 0;
384: continue;
385: }
386: relerr = 0;
387: if (a1 || minus)
388: relerr++;
389: switch(c) {
390: case ' ':
391: case '\t':
392: continue;
393:
394: case '+':
395: minus++;
396: if (a1==0)
397: a1 = dot;
398: continue;
399:
400: case '-':
401: case '^':
402: minus--;
403: if (a1==0)
404: a1 = dot;
405: continue;
406:
407: case '?':
408: case '/':
409: compile(c);
410: a1 = dot;
411: for (;;) {
412: if (c=='/') {
413: a1++;
414: if (a1 > dol)
415: a1 = zero;
416: } else {
417: a1--;
418: if (a1 < zero)
419: a1 = dol;
420: }
421: if (execute(0, a1))
422: break;
423: if (a1==dot)
424: error(Q);
425: }
426: break;
427:
428: case '$':
429: a1 = dol;
430: break;
431:
432: case '.':
433: a1 = dot;
434: break;
435:
436: case '\'':
437: if ((c = getchr()) < 'a' || c > 'z')
438: error(Q);
439: for (a1=zero; a1<=dol; a1++)
440: if (names[c-'a'] == (*a1 & ~01))
441: break;
442: break;
443:
444: default:
445: peekc = c;
446: if (a1==0)
447: return(0);
448: a1 += minus;
449: if (a1<zero || a1>dol)
450: error(Q);
451: return(a1);
452: }
453: if (relerr)
454: error(Q);
455: }
456: }
457:
458: setdot()
459: {
460: if (addr2 == 0)
461: addr1 = addr2 = dot;
462: if (addr1 > addr2)
463: error(Q);
464: }
465:
466: setall()
467: {
468: if (addr2==0) {
469: addr1 = zero+1;
470: addr2 = dol;
471: if (dol==zero)
472: addr1 = zero;
473: }
474: setdot();
475: }
476:
477: setnoaddr()
478: {
479: if (addr2)
480: error(Q);
481: }
482:
483: nonzero()
484: {
485: if (addr1<=zero || addr2>dol)
486: error(Q);
487: }
488:
489: newline()
490: {
491: register c;
492:
493: if ((c = getchr()) == '\n')
494: return;
495: if (c=='p' || c=='l') {
496: pflag++;
497: if (c=='l')
498: listf++;
499: if (getchr() == '\n')
500: return;
501: }
502: error(Q);
503: }
504:
505: filename(comm)
506: {
507: register char *p1, *p2;
508: register c;
509:
510: count = 0;
511: c = getchr();
512: if (c=='\n' || c==EOF) {
513: p1 = savedfile;
514: if (*p1==0 && comm!='f')
515: error(Q);
516: p2 = file;
517: while (*p2++ = *p1++)
518: ;
519: return;
520: }
521: if (c!=' ')
522: error(Q);
523: while ((c = getchr()) == ' ')
524: ;
525: if (c=='\n')
526: error(Q);
527: p1 = file;
528: do {
529: *p1++ = c;
530: if (c==' ' || c==EOF)
531: error(Q);
532: } while ((c = getchr()) != '\n');
533: *p1++ = 0;
534: if (savedfile[0]==0 || comm=='e' || comm=='f') {
535: p1 = savedfile;
536: p2 = file;
537: while (*p1++ = *p2++)
538: ;
539: }
540: }
541:
542: exfile()
543: {
544: close(io);
545: io = -1;
546: if (vflag) {
547: putd();
548: putchr('\n');
549: }
550: }
551:
552: void
553: onintr()
554: {
555: /* not necessary: (void)signal(SIGINT, onintr); */
556: putchr('\n');
557: lastc = '\n';
558: error(Q);
559: }
560:
561: void
562: onhup()
563: {
564: /* not necessary: (void)signal(SIGINT, SIG_IGN); */
565: /* not necessary: (void)signal(SIGHUP, SIG_IGN); */
566: if (dol > zero) {
567: addr1 = zero+1;
568: addr2 = dol;
569: io = creat("ed.hup", 0666);
570: if (io > 0)
571: putfile();
572: }
573: fchange = 0;
574: quit();
575: }
576:
577: error(s)
578: char *s;
579: {
580: register c;
581:
582: wrapp = 0;
583: listf = 0;
584: putchr('?');
585: puts(s);
586: count = 0;
587: lseek(0, (long)0, 2);
588: pflag = 0;
589: if (globp)
590: lastc = '\n';
591: globp = 0;
592: peekc = lastc;
593: if(lastc)
594: while ((c = getchr()) != '\n' && c != EOF)
595: ;
596: if (io > 0) {
597: close(io);
598: io = -1;
599: }
600: longjmp(savej, 1);
601: }
602:
603: getchr()
604: {
605: char c;
606: if (lastc=peekc) {
607: peekc = 0;
608: return(lastc);
609: }
610: if (globp) {
611: if ((lastc = *globp++) != 0)
612: return(lastc);
613: globp = 0;
614: return(EOF);
615: }
616: if (read(0, &c, 1) <= 0)
617: return(lastc = EOF);
618: lastc = c&0177;
619: return(lastc);
620: }
621:
622: gettty()
623: {
624: register c;
625: register char *gf;
626: register char *p;
627:
628: p = linebuf;
629: gf = globp;
630: while ((c = getchr()) != '\n') {
631: if (c==EOF) {
632: if (gf)
633: peekc = c;
634: return(c);
635: }
636: if ((c &= 0177) == 0)
637: continue;
638: *p++ = c;
639: if (p >= &linebuf[LBSIZE-2])
640: error(Q);
641: }
642: *p++ = 0;
643: if (linebuf[0]=='.' && linebuf[1]==0)
644: return(EOF);
645: return(0);
646: }
647:
648: getfile()
649: {
650: register c;
651: register char *lp, *fp;
652:
653: lp = linebuf;
654: fp = nextip;
655: do {
656: if (--ninbuf < 0) {
657: if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0)
658: return(EOF);
659: fp = genbuf;
660: while(fp < &genbuf[ninbuf]) {
661: if (*fp++ & 0200) {
662: break;
663: }
664: }
665: fp = genbuf;
666: }
667: c = *fp++;
668: if (c=='\0')
669: continue;
670: if (c&0200 || lp >= &linebuf[LBSIZE]) {
671: lastc = '\n';
672: error(Q);
673: }
674: *lp++ = c;
675: count++;
676: } while (c != '\n');
677: *--lp = 0;
678: nextip = fp;
679: return(0);
680: }
681:
682: putfile()
683: {
684: int *a1, n;
685: register char *fp, *lp;
686: register nib;
687:
688: nib = 512;
689: fp = genbuf;
690: a1 = addr1;
691: do {
692: lp = getline(*a1++);
693: for (;;) {
694: if (--nib < 0) {
695: n = fp-genbuf;
696: if(write(io, genbuf, n) != n) {
697: puts(WRERR);
698: error(Q);
699: }
700: nib = 511;
701: fp = genbuf;
702: }
703: count++;
704: if ((*fp++ = *lp++) == 0) {
705: fp[-1] = '\n';
706: break;
707: }
708: }
709: } while (a1 <= addr2);
710: n = fp-genbuf;
711: if(write(io, genbuf, n) != n) {
712: puts(WRERR);
713: error(Q);
714: }
715: }
716:
717: append(f, a)
718: int *a;
719: int (*f)();
720: {
721: register *a1, *a2, *rdot;
722: int nline, tl;
723:
724: nline = 0;
725: dot = a;
726: while ((*f)() == 0) {
727: if ((dol-zero)+1 >= nlall) {
728: int *ozero = zero;
729: nlall += 512;
730: if ((zero = (int *)realloc((char *)zero, nlall*sizeof(int)))==NULL) {
731: lastc = '\n';
732: zero = ozero;
733: error("MEM?");
734: }
735: dot += zero - ozero;
736: dol += zero - ozero;
737: }
738: tl = putline();
739: nline++;
740: a1 = ++dol;
741: a2 = a1+1;
742: rdot = ++dot;
743: while (a1 > rdot)
744: *--a2 = *--a1;
745: *rdot = tl;
746: }
747: return(nline);
748: }
749:
750: callunix()
751: {
752: register sig_t savint;
753: register int pid, rpid;
754: int retcode;
755:
756: setnoaddr();
757: if ((pid = fork()) == 0) {
758: signal(SIGHUP, oldhup);
759: signal(SIGQUIT, oldquit);
760: execl(_PATH_BSHELL, "sh", "-t", 0);
761: exit(0100);
762: }
763: savint = signal(SIGINT, SIG_IGN);
764: while ((rpid = wait(&retcode)) != pid && rpid != -1)
765: ;
766: signal(SIGINT, savint);
767: puts("!");
768: }
769:
770: void
771: quit()
772: {
773: if (vflag && fchange && dol!=zero) {
774: fchange = 0;
775: error(Q);
776: }
777: unlink(tfname);
778: exit(0);
779: }
780:
781: delete()
782: {
783: setdot();
784: newline();
785: nonzero();
786: rdelete(addr1, addr2);
787: }
788:
789: rdelete(ad1, ad2)
790: int *ad1, *ad2;
791: {
792: register *a1, *a2, *a3;
793:
794: a1 = ad1;
795: a2 = ad2+1;
796: a3 = dol;
797: dol -= a2 - a1;
798: do {
799: *a1++ = *a2++;
800: } while (a2 <= a3);
801: a1 = ad1;
802: if (a1 > dol)
803: a1 = dol;
804: dot = a1;
805: fchange = 1;
806: }
807:
808: gdelete()
809: {
810: register *a1, *a2, *a3;
811:
812: a3 = dol;
813: for (a1=zero+1; (*a1&01)==0; a1++)
814: if (a1>=a3)
815: return;
816: for (a2=a1+1; a2<=a3;) {
817: if (*a2&01) {
818: a2++;
819: dot = a1;
820: } else
821: *a1++ = *a2++;
822: }
823: dol = a1-1;
824: if (dot>dol)
825: dot = dol;
826: fchange = 1;
827: }
828:
829: char *
830: getline(tl)
831: {
832: register char *bp, *lp;
833: register nl;
834:
835: lp = linebuf;
836: bp = getblock(tl, READ);
837: nl = nleft;
838: tl &= ~0377;
839: while (*lp++ = *bp++)
840: if (--nl == 0) {
841: bp = getblock(tl+=0400, READ);
842: nl = nleft;
843: }
844: return(linebuf);
845: }
846:
847: putline()
848: {
849: register char *bp, *lp;
850: register nl;
851: int tl;
852:
853: fchange = 1;
854: lp = linebuf;
855: tl = tline;
856: bp = getblock(tl, WRITE);
857: nl = nleft;
858: tl &= ~0377;
859: while (*bp = *lp++) {
860: if (*bp++ == '\n') {
861: *--bp = 0;
862: linebp = lp;
863: break;
864: }
865: if (--nl == 0) {
866: bp = getblock(tl+=0400, WRITE);
867: nl = nleft;
868: }
869: }
870: nl = tline;
871: tline += (((lp-linebuf)+03)>>1)&077776;
872: return(nl);
873: }
874:
875: char *
876: getblock(atl, iof)
877: {
878: extern read(), write();
879: register bno, off;
880: register char *p1, *p2;
881: register int n;
882:
883: bno = (atl>>8)&0377;
884: off = (atl<<1)&0774;
885: if (bno >= 255) {
886: lastc = '\n';
887: error(T);
888: }
889: nleft = 512 - off;
890: if (bno==iblock) {
891: ichanged |= iof;
892: return(ibuff+off);
893: }
894: if (bno==oblock)
895: return(obuff+off);
896: if (iof==READ) {
897: if (ichanged) {
898: blkio(iblock, ibuff, write);
899: }
900: ichanged = 0;
901: iblock = bno;
902: blkio(bno, ibuff, read);
903: return(ibuff+off);
904: }
905: if (oblock>=0) {
906: blkio(oblock, obuff, write);
907: }
908: oblock = bno;
909: return(obuff+off);
910: }
911:
912: blkio(b, buf, iofcn)
913: char *buf;
914: int (*iofcn)();
915: {
916: lseek(tfile, (long)b<<9, 0);
917: if ((*iofcn)(tfile, buf, 512) != 512) {
918: error(T);
919: }
920: }
921:
922: init()
923: {
924: register *markp;
925:
926: close(tfile);
927: tline = 2;
928: for (markp = names; markp < &names[26]; )
929: *markp++ = 0;
930: subnewa = 0;
931: anymarks = 0;
932: iblock = -1;
933: oblock = -1;
934: ichanged = 0;
935: close(creat(tfname, 0600));
936: tfile = open(tfname, 2);
937: dot = dol = zero;
938: }
939:
940: global(k)
941: {
942: register char *gp;
943: register c;
944: register int *a1;
945: char globuf[GBSIZE];
946:
947: if (globp)
948: error(Q);
949: setall();
950: nonzero();
951: if ((c=getchr())=='\n')
952: error(Q);
953: compile(c);
954: gp = globuf;
955: while ((c = getchr()) != '\n') {
956: if (c==EOF)
957: error(Q);
958: if (c=='\\') {
959: c = getchr();
960: if (c!='\n')
961: *gp++ = '\\';
962: }
963: *gp++ = c;
964: if (gp >= &globuf[GBSIZE-2])
965: error(Q);
966: }
967: *gp++ = '\n';
968: *gp++ = 0;
969: for (a1=zero; a1<=dol; a1++) {
970: *a1 &= ~01;
971: if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k)
972: *a1 |= 01;
973: }
974: /*
975: * Special case: g/.../d (avoid n^2 algorithm)
976: */
977: if (globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') {
978: gdelete();
979: return;
980: }
981: for (a1=zero; a1<=dol; a1++) {
982: if (*a1 & 01) {
983: *a1 &= ~01;
984: dot = a1;
985: globp = globuf;
986: commands();
987: a1 = zero;
988: }
989: }
990: }
991:
992: join()
993: {
994: register char *gp, *lp;
995: register *a1;
996:
997: gp = genbuf;
998: for (a1=addr1; a1<=addr2; a1++) {
999: lp = getline(*a1);
1000: while (*gp = *lp++)
1001: if (gp++ >= &genbuf[LBSIZE-2])
1002: error(Q);
1003: }
1004: lp = linebuf;
1005: gp = genbuf;
1006: while (*lp++ = *gp++)
1007: ;
1008: *addr1 = putline();
1009: if (addr1<addr2)
1010: rdelete(addr1+1, addr2);
1011: dot = addr1;
1012: }
1013:
1014: substitute(inglob)
1015: {
1016: register *markp, *a1, nl;
1017: int gsubf;
1018: int getsub();
1019:
1020: gsubf = compsub();
1021: for (a1 = addr1; a1 <= addr2; a1++) {
1022: int *ozero;
1023: if (execute(0, a1)==0)
1024: continue;
1025: inglob |= 01;
1026: dosub();
1027: if (gsubf) {
1028: while (*loc2) {
1029: if (execute(1, (int *)0)==0)
1030: break;
1031: dosub();
1032: }
1033: }
1034: subnewa = putline();
1035: *a1 &= ~01;
1036: if (anymarks) {
1037: for (markp = names; markp < &names[26]; markp++)
1038: if (*markp == *a1)
1039: *markp = subnewa;
1040: }
1041: subolda = *a1;
1042: *a1 = subnewa;
1043: ozero = zero;
1044: nl = append(getsub, a1);
1045: nl += zero-ozero;
1046: a1 += nl;
1047: addr2 += nl;
1048: }
1049: if (inglob==0)
1050: error(Q);
1051: }
1052:
1053: compsub()
1054: {
1055: register seof, c;
1056: register char *p;
1057:
1058: if ((seof = getchr()) == '\n' || seof == ' ')
1059: error(Q);
1060: compile(seof);
1061: p = rhsbuf;
1062: for (;;) {
1063: c = getchr();
1064: if (c=='\\')
1065: c = getchr() | 0200;
1066: if (c=='\n') {
1067: if (globp)
1068: c |= 0200;
1069: else
1070: error(Q);
1071: }
1072: if (c==seof)
1073: break;
1074: *p++ = c;
1075: if (p >= &rhsbuf[LBSIZE/2])
1076: error(Q);
1077: }
1078: *p++ = 0;
1079: if ((peekc = getchr()) == 'g') {
1080: peekc = 0;
1081: newline();
1082: return(1);
1083: }
1084: newline();
1085: return(0);
1086: }
1087:
1088: getsub()
1089: {
1090: register char *p1, *p2;
1091:
1092: p1 = linebuf;
1093: if ((p2 = linebp) == 0)
1094: return(EOF);
1095: while (*p1++ = *p2++)
1096: ;
1097: linebp = 0;
1098: return(0);
1099: }
1100:
1101: dosub()
1102: {
1103: register char *lp, *sp, *rp;
1104: int c;
1105:
1106: lp = linebuf;
1107: sp = genbuf;
1108: rp = rhsbuf;
1109: while (lp < loc1)
1110: *sp++ = *lp++;
1111: while (c = *rp++&0377) {
1112: if (c=='&') {
1113: sp = place(sp, loc1, loc2);
1114: continue;
1115: } else if (c&0200 && (c &= 0177) >='1' && c < nbra+'1') {
1116: sp = place(sp, braslist[c-'1'], braelist[c-'1']);
1117: continue;
1118: }
1119: *sp++ = c&0177;
1120: if (sp >= &genbuf[LBSIZE])
1121: error(Q);
1122: }
1123: lp = loc2;
1124: loc2 = sp - genbuf + linebuf;
1125: while (*sp++ = *lp++)
1126: if (sp >= &genbuf[LBSIZE])
1127: error(Q);
1128: lp = linebuf;
1129: sp = genbuf;
1130: while (*lp++ = *sp++)
1131: ;
1132: }
1133:
1134: char *
1135: place(sp, l1, l2)
1136: register char *sp, *l1, *l2;
1137: {
1138:
1139: while (l1 < l2) {
1140: *sp++ = *l1++;
1141: if (sp >= &genbuf[LBSIZE])
1142: error(Q);
1143: }
1144: return(sp);
1145: }
1146:
1147: move(cflag)
1148: {
1149: register int *adt, *ad1, *ad2;
1150: int getcopy();
1151:
1152: setdot();
1153: nonzero();
1154: if ((adt = address())==0)
1155: error(Q);
1156: newline();
1157: if (cflag) {
1158: int *ozero, delta;
1159: ad1 = dol;
1160: ozero = zero;
1161: append(getcopy, ad1++);
1162: ad2 = dol;
1163: delta = zero - ozero;
1164: ad1 += delta;
1165: adt += delta;
1166: } else {
1167: ad2 = addr2;
1168: for (ad1 = addr1; ad1 <= ad2;)
1169: *ad1++ &= ~01;
1170: ad1 = addr1;
1171: }
1172: ad2++;
1173: if (adt<ad1) {
1174: dot = adt + (ad2-ad1);
1175: if ((++adt)==ad1)
1176: return;
1177: reverse(adt, ad1);
1178: reverse(ad1, ad2);
1179: reverse(adt, ad2);
1180: } else if (adt >= ad2) {
1181: dot = adt++;
1182: reverse(ad1, ad2);
1183: reverse(ad2, adt);
1184: reverse(ad1, adt);
1185: } else
1186: error(Q);
1187: fchange = 1;
1188: }
1189:
1190: reverse(a1, a2)
1191: register int *a1, *a2;
1192: {
1193: register int t;
1194:
1195: for (;;) {
1196: t = *--a2;
1197: if (a2 <= a1)
1198: return;
1199: *a2 = *a1;
1200: *a1++ = t;
1201: }
1202: }
1203:
1204: getcopy()
1205: {
1206: if (addr1 > addr2)
1207: return(EOF);
1208: getline(*addr1++);
1209: return(0);
1210: }
1211:
1212: compile(aeof)
1213: {
1214: register eof, c;
1215: register char *ep;
1216: char *lastep;
1217: char bracket[NBRA], *bracketp;
1218: int cclcnt;
1219:
1220: ep = expbuf;
1221: eof = aeof;
1222: bracketp = bracket;
1223: if ((c = getchr()) == eof) {
1224: if (*ep==0)
1225: error(Q);
1226: return;
1227: }
1228: circfl = 0;
1229: nbra = 0;
1230: if (c=='^') {
1231: c = getchr();
1232: circfl++;
1233: }
1234: peekc = c;
1235: lastep = 0;
1236: for (;;) {
1237: if (ep >= &expbuf[ESIZE])
1238: goto cerror;
1239: c = getchr();
1240: if (c==eof) {
1241: if (bracketp != bracket)
1242: goto cerror;
1243: *ep++ = CEOF;
1244: return;
1245: }
1246: if (c!='*')
1247: lastep = ep;
1248: switch (c) {
1249:
1250: case '\\':
1251: if ((c = getchr())=='(') {
1252: if (nbra >= NBRA)
1253: goto cerror;
1254: *bracketp++ = nbra;
1255: *ep++ = CBRA;
1256: *ep++ = nbra++;
1257: continue;
1258: }
1259: if (c == ')') {
1260: if (bracketp <= bracket)
1261: goto cerror;
1262: *ep++ = CKET;
1263: *ep++ = *--bracketp;
1264: continue;
1265: }
1266: if (c>='1' && c<'1'+NBRA) {
1267: *ep++ = CBACK;
1268: *ep++ = c-'1';
1269: continue;
1270: }
1271: *ep++ = CCHR;
1272: if (c=='\n')
1273: goto cerror;
1274: *ep++ = c;
1275: continue;
1276:
1277: case '.':
1278: *ep++ = CDOT;
1279: continue;
1280:
1281: case '\n':
1282: goto cerror;
1283:
1284: case '*':
1285: if (lastep==0 || *lastep==CBRA || *lastep==CKET)
1286: goto defchar;
1287: *lastep |= STAR;
1288: continue;
1289:
1290: case '$':
1291: if ((peekc=getchr()) != eof)
1292: goto defchar;
1293: *ep++ = CDOL;
1294: continue;
1295:
1296: case '[':
1297: *ep++ = CCL;
1298: *ep++ = 0;
1299: cclcnt = 1;
1300: if ((c=getchr()) == '^') {
1301: c = getchr();
1302: ep[-2] = NCCL;
1303: }
1304: do {
1305: if (c=='\n')
1306: goto cerror;
1307: if (c=='-' && ep[-1]!=0) {
1308: if ((c=getchr())==']') {
1309: *ep++ = '-';
1310: cclcnt++;
1311: break;
1312: }
1313: while (ep[-1]<c) {
1314: *ep = ep[-1]+1;
1315: ep++;
1316: cclcnt++;
1317: if (ep>=&expbuf[ESIZE])
1318: goto cerror;
1319: }
1320: }
1321: *ep++ = c;
1322: cclcnt++;
1323: if (ep >= &expbuf[ESIZE])
1324: goto cerror;
1325: } while ((c = getchr()) != ']');
1326: lastep[1] = cclcnt;
1327: continue;
1328:
1329: defchar:
1330: default:
1331: *ep++ = CCHR;
1332: *ep++ = c;
1333: }
1334: }
1335: cerror:
1336: expbuf[0] = 0;
1337: nbra = 0;
1338: error(Q);
1339: }
1340:
1341: execute(gf, addr)
1342: int *addr;
1343: {
1344: register char *p1, *p2, c;
1345:
1346: for (c=0; c<NBRA; c++) {
1347: braslist[c] = 0;
1348: braelist[c] = 0;
1349: }
1350: if (gf) {
1351: if (circfl)
1352: return(0);
1353: p1 = linebuf;
1354: p2 = genbuf;
1355: while (*p1++ = *p2++)
1356: ;
1357: locs = p1 = loc2;
1358: } else {
1359: if (addr==zero)
1360: return(0);
1361: p1 = getline(*addr);
1362: locs = 0;
1363: }
1364: p2 = expbuf;
1365: if (circfl) {
1366: loc1 = p1;
1367: return(advance(p1, p2));
1368: }
1369: /* fast check for first character */
1370: if (*p2==CCHR) {
1371: c = p2[1];
1372: do {
1373: if (*p1!=c)
1374: continue;
1375: if (advance(p1, p2)) {
1376: loc1 = p1;
1377: return(1);
1378: }
1379: } while (*p1++);
1380: return(0);
1381: }
1382: /* regular algorithm */
1383: do {
1384: if (advance(p1, p2)) {
1385: loc1 = p1;
1386: return(1);
1387: }
1388: } while (*p1++);
1389: return(0);
1390: }
1391:
1392: advance(lp, ep)
1393: register char *ep, *lp;
1394: {
1395: register char *curlp;
1396: int i;
1397:
1398: for (;;) switch (*ep++) {
1399:
1400: case CCHR:
1401: if (*ep++ == *lp++)
1402: continue;
1403: return(0);
1404:
1405: case CDOT:
1406: if (*lp++)
1407: continue;
1408: return(0);
1409:
1410: case CDOL:
1411: if (*lp==0)
1412: continue;
1413: return(0);
1414:
1415: case CEOF:
1416: loc2 = lp;
1417: return(1);
1418:
1419: case CCL:
1420: if (cclass(ep, *lp++, 1)) {
1421: ep += *ep;
1422: continue;
1423: }
1424: return(0);
1425:
1426: case NCCL:
1427: if (cclass(ep, *lp++, 0)) {
1428: ep += *ep;
1429: continue;
1430: }
1431: return(0);
1432:
1433: case CBRA:
1434: braslist[*ep++] = lp;
1435: continue;
1436:
1437: case CKET:
1438: braelist[*ep++] = lp;
1439: continue;
1440:
1441: case CBACK:
1442: if (braelist[i = *ep++]==0)
1443: error(Q);
1444: if (backref(i, lp)) {
1445: lp += braelist[i] - braslist[i];
1446: continue;
1447: }
1448: return(0);
1449:
1450: case CBACK|STAR:
1451: if (braelist[i = *ep++] == 0)
1452: error(Q);
1453: curlp = lp;
1454: while (backref(i, lp))
1455: lp += braelist[i] - braslist[i];
1456: while (lp >= curlp) {
1457: if (advance(lp, ep))
1458: return(1);
1459: lp -= braelist[i] - braslist[i];
1460: }
1461: continue;
1462:
1463: case CDOT|STAR:
1464: curlp = lp;
1465: while (*lp++)
1466: ;
1467: goto star;
1468:
1469: case CCHR|STAR:
1470: curlp = lp;
1471: while (*lp++ == *ep)
1472: ;
1473: ep++;
1474: goto star;
1475:
1476: case CCL|STAR:
1477: case NCCL|STAR:
1478: curlp = lp;
1479: while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)))
1480: ;
1481: ep += *ep;
1482: goto star;
1483:
1484: star:
1485: do {
1486: lp--;
1487: if (lp==locs)
1488: break;
1489: if (advance(lp, ep))
1490: return(1);
1491: } while (lp > curlp);
1492: return(0);
1493:
1494: default:
1495: error(Q);
1496: }
1497: }
1498:
1499: backref(i, lp)
1500: register i;
1501: register char *lp;
1502: {
1503: register char *bp;
1504:
1505: bp = braslist[i];
1506: while (*bp++ == *lp++)
1507: if (bp >= braelist[i])
1508: return(1);
1509: return(0);
1510: }
1511:
1512: cclass(set, c, af)
1513: register char *set, c;
1514: {
1515: register n;
1516:
1517: if (c==0)
1518: return(0);
1519: n = *set++;
1520: while (--n)
1521: if (*set++ == c)
1522: return(af);
1523: return(!af);
1524: }
1525:
1526: putd()
1527: {
1528: register r;
1529:
1530: r = count%10;
1531: count /= 10;
1532: if (count)
1533: putd();
1534: putchr(r + '0');
1535: }
1536:
1537: puts(sp)
1538: register char *sp;
1539: {
1540: col = 0;
1541: while (*sp)
1542: putchr(*sp++);
1543: putchr('\n');
1544: }
1545:
1546: char line[70];
1547: char *linp = line;
1548:
1549: putchr(ac)
1550: {
1551: register char *lp;
1552: register c;
1553:
1554: lp = linp;
1555: c = ac;
1556: if (listf) {
1557: col++;
1558: if (col >= 72) {
1559: col = 0;
1560: *lp++ = '\\';
1561: *lp++ = '\n';
1562: }
1563: if (c=='\t') {
1564: c = '>';
1565: goto esc;
1566: }
1567: if (c=='\b') {
1568: c = '<';
1569: esc:
1570: *lp++ = '-';
1571: *lp++ = '\b';
1572: *lp++ = c;
1573: goto out;
1574: }
1575: if (c<' ' && c!= '\n') {
1576: *lp++ = '\\';
1577: *lp++ = (c>>3)+'0';
1578: *lp++ = (c&07)+'0';
1579: col += 2;
1580: goto out;
1581: }
1582: }
1583: *lp++ = c;
1584: out:
1585: if(c == '\n' || lp >= &line[64]) {
1586: linp = line;
1587: write(1, line, lp-line);
1588: return;
1589: }
1590: linp = lp;
1591: }
1592:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.