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