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