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