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