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