11 FNSIZE = 128, /* file name */
12 LBSIZE = 4096, /* max line size */
13 BLKSIZE = 4096, /* block size in temp file */
14 NBLK = 8191, /* max size of temp file */
15 ESIZE = 256, /* max size of reg exp */
16 GBSIZE = 256, /* max size of global command */
17 MAXSUB = 9, /* max number of sub reg exp */
18 ESCFLG = Runemax, /* escape Rune - user defined code */
57 Rune rhsbuf[LBSIZE/sizeof(Rune)];
58 char savedfile[FNSIZE];
71 char WRERR[] = "WRITE ERROR";
73 char hex[] = "0123456789abcdef";
81 int append(int(*)(void), int*);
92 Rune* getblock(int, int);
106 void notifyf(void*, char*);
107 Rune* place(Rune*, Rune*, Rune*);
116 void rdelete(int*, int*);
117 void regerror(char *);
118 void reverse(int*, int*);
119 void setnoaddr(void);
122 void substitute(int);
125 main(int argc, char *argv[])
129 Binit(&bcons, 0, OREAD);
130 Blethal(&bcons, nil);
140 if(*argv && (strcmp(*argv, "-") == 0)) {
155 if(p2 >= &savedfile[sizeof(savedfile)])
159 zero = malloc((nlall+5)*sizeof(int*));
160 tfname = mktemp(strdup("/tmp/eXXXXX"));
185 if(c != ',' && c != ';')
198 if(lastsep != '\n' && a1 == 0)
200 if((addr2=a1) == 0) {
221 rdelete(addr1, addr2);
222 append(gettty, addr1-1);
228 rdelete(addr1, addr2);
236 if(vflag && fchange) {
270 if(c < 'a' || c > 'z')
273 names[c-'a'] = *addr2 & ~01;
316 if((io=open(file, OREAD)) < 0) {
320 if((d = dirfstat(io)) != nil){
321 if(d->mode & DMAPPEND)
322 print("warning: %s is append only\n", file);
325 Binit(&iobuf, io, OREAD);
326 Blethal(&iobuf, nil);
330 append(getfile, addr2);
338 substitute(globp != 0);
348 if((*addr2&~01) != subnewa)
364 if(temp != 'q' && temp != 'Q') {
370 ((io = open(file, OWRITE)) == -1) ||
371 ((seek(io, 0L, 2)) == -1))
372 if((io = create(file, OWRITE, 0666)) < 0)
374 Binit(&iobuf, io, OWRITE);
379 if(addr1<=zero+1 && addr2==dol)
391 count = addr2 - zero;
421 putshst(getline(*a1++));
422 } while(a1 <= addr2);
432 int sign, *a, opcnt, nextopand, *b, c;
441 } while(c == ' ' || c == '\t');
442 if(c >= '0' && c <= '9') {
457 if(opcnt || c < 'a' || c > 'z')
462 } while(a <= dol && names[c-'a'] != (*a & ~01));
482 if(nextopand == opcnt) {
484 if(a < zero || dol < a)
485 continue; /* error(Q); */
487 if(c != '+' && c != '-' && c != '^') {
501 } while(zero <= a && a <= dol);
514 if(c < '0' || c > '9')
526 addr1 = zero + (dol>zero);
547 if(addr1 < zero+i || addr2 > dol || addr1 > addr2)
557 if(c == '\n' || c == EOF)
559 if(c == 'p' || c == 'l' || c == 'n') {
582 if(c == '\n' || c == EOF) {
584 if(*p1 == 0 && comm != 'f')
593 while((c=getchr()) == ' ')
599 if(p1 >= &file[sizeof(file)-6] || c == ' ' || c == EOF)
602 p1 += runetochar(p1, &rune);
603 } while((c=getchr()) != '\n');
605 if(savedfile[0] == 0 || comm == 'e' || comm == 'f') {
618 if(Bflush(&iobuf) < 0)
646 if(c == '\n' || c == EOF)
671 io = create("ed.hup", OWRITE, 0666);
673 Binit(&iobuf, io, OWRITE);
682 notifyf(void *a, char *s)
684 if(strcmp(s, "interrupt") == 0){
685 if(rescuing || waiting)
690 notejmp(a, savej, 0);
692 if(strcmp(s, "hangup") == 0){
697 fprint(2, "ed: note: %s\n", s);
709 if((lastc=*globp++) != 0)
714 lastc = Bgetrune(&bcons);
740 if(p >= &linebuf[LBSIZE-sizeof(Rune)])
753 if(linebuf[0] == '.' && linebuf[1] == 0)
766 c = Bgetrune(&iobuf);
769 putst("'\\n' appended");
774 if(lp >= &linebuf[LBSIZE]) {
799 if(Bputrune(&iobuf, '\n') < 0)
803 if(Bputrune(&iobuf, c) < 0)
806 } while(a1 <= addr2);
807 if(Bflush(&iobuf) < 0)
812 append(int (*f)(void), int *a)
814 int *a1, *a2, *rdot, nline, tl;
819 if((dol-zero) >= nlall) {
821 a1 = realloc(zero, (nlall+5)*sizeof(int*));
826 tl = a1 - zero; /* relocate pointers */
848 if(i && (given || dol > zero)) {
854 append(gettty, addr2);
861 static int bformat, bnum; /* 0 */
866 if(peekc == '-' || peekc == '+') {
889 addr1 = addr2-bpagesize;
906 while((c=getchr()) != EOF && c != '\n')
907 if(p < &buf[sizeof(buf) - 6]) {
909 p += runetochar(p, &rune);
914 execl("/bin/rc", "rc", "-c", buf, nil);
915 exits("execl failed");
918 while(waitpid() != pid)
928 if(vflag && fchange && dol!=zero) {
944 rdelete(int *ad1, int *ad2)
968 for(a1=zero; (*a1&01)==0; a1++)
971 for(a2=a1+1; a2<=a3;) {
991 bp = getblock(tl, OREAD);
993 tl &= ~((BLKSIZE/sizeof(Rune)) - 1);
994 while(*lp++ = *bp++) {
997 bp = getblock(tl += BLKSIZE/sizeof(Rune), OREAD);
1013 bp = getblock(tl, OWRITE);
1015 tl &= ~((BLKSIZE/sizeof(Rune))-1);
1016 while(*bp = *lp++) {
1024 tl += BLKSIZE/sizeof(Rune);
1025 bp = getblock(tl, OWRITE);
1030 tline += ((lp-linebuf) + 03) & 077776;
1035 blkio(int b, uchar *buf, long (*iofcn)(int, void *, long))
1037 seek(tfile, b*BLKSIZE, 0);
1038 if((*iofcn)(tfile, buf, BLKSIZE) != BLKSIZE) {
1044 getblock(int atl, int iof)
1048 static uchar ibuff[BLKSIZE];
1049 static uchar obuff[BLKSIZE];
1051 bno = atl / (BLKSIZE/sizeof(Rune));
1052 off = (atl*sizeof(Rune)) & (BLKSIZE-1) & ~03;
1057 nleft = BLKSIZE - off;
1060 return (Rune*)(ibuff+off);
1063 return (Rune*)(obuff+off);
1066 blkio(iblock, ibuff, write);
1069 blkio(bno, ibuff, read);
1070 return (Rune*)(ibuff+off);
1073 blkio(oblock, obuff, write);
1075 return (Rune*)(obuff+off);
1085 for(markp = names; markp < &names[26]; )
1092 if((tfile = create(tfname, ORDWR, 0600)) < 0){
1102 Rune *gp, globuf[GBSIZE];
1108 squeeze(dol > zero);
1114 while((c=getchr()) != '\n') {
1123 if(gp >= &globuf[GBSIZE-2])
1130 for(a1=zero; a1<=dol; a1++) {
1132 if(a1 >= addr1 && a1 <= addr2 && match(a1) == k)
1137 * Special case: g/.../d (avoid n^2 algorithm)
1139 if(globuf[0] == 'd' && globuf[1] == '\n' && globuf[2] == 0) {
1143 for(a1=zero; a1<=dol; a1++) {
1162 for(a1=addr1; a1<=addr2; a1++) {
1165 if(gp++ >= &genbuf[LBSIZE-sizeof(Rune)])
1170 while(*lp++ = *gp++)
1174 rdelete(addr1+1, addr2);
1179 substitute(int inglob)
1181 int *mp, *a1, nl, gsubf, n;
1183 n = getnum(); /* OK even if n==0 */
1185 for(a1 = addr1; a1 <= addr2; a1++) {
1191 int span = loc2-loc1;
1197 if(span == 0) { /* null RE match */
1206 subnewa = putline();
1209 for(mp=names; mp<&names[26]; mp++)
1216 nl = append(getsub, a1);
1234 if(seof == '\n' || seof == ' ')
1243 if(p >= &rhsbuf[nelem(rhsbuf)])
1246 if(c == '\n' && (!globp || !globp[0])) {
1254 if(p >= &rhsbuf[nelem(rhsbuf)])
1274 if((p2 = linebp) == 0)
1276 while(*p1++ = *p2++)
1295 sp = place(sp, loc1, loc2);
1298 if(c == ESCFLG && (c = *rp++) >= '1' && c < MAXSUB+'0') {
1300 if(subexp[n].rsp && subexp[n].rep) {
1301 sp = place(sp, subexp[n].rsp, subexp[n].rep);
1307 if(sp >= &genbuf[LBSIZE])
1311 loc2 = sp - genbuf + linebuf;
1312 while(*sp++ = *lp++)
1313 if(sp >= &genbuf[LBSIZE])
1317 while(*lp++ = *sp++)
1322 place(Rune *sp, Rune *l1, Rune *l2)
1327 if(sp >= &genbuf[LBSIZE])
1336 int *adt, *ad1, *ad2;
1339 if((adt = address())==0) /* address() guarantees addr is in range */
1346 append(getcopy, ad1++);
1348 delta = zero - ozero;
1353 for(ad1 = addr1; ad1 <= ad2;)
1359 dot = adt + (ad2-ad1);
1377 reverse(int *a1, int *a2)
1406 if((c = getchr()) == '\n') {
1422 if(ep >= expbuf+sizeof(expbuf)) {
1426 ep += runetochar(ep, &c);
1427 if((c = getchr()) == '\n') {
1432 if(ep >= expbuf+sizeof(expbuf)) {
1436 ep += runetochar(ep, &c);
1437 } while((c = getchr()) != eof && c != '\n');
1441 pattern = regcomp(expbuf);
1452 subexp[0].rsp = getline(*addr);
1454 subexp[0].rsp = loc2;
1456 if(rregexec(pattern, linebuf, subexp, MAXSUB)) {
1457 loc1 = subexp[0].rsp;
1458 loc2 = subexp[0].rep;
1485 sp += chartorune(&r, sp);
1513 if(linp != line && linp[-1] == ' ') {
1518 if(col > (72-6-2)) {
1525 if(c=='\b' || c=='\t' || c=='\\') {
1534 if(c<' ' || c>='\177') {
1538 *lp++ = hex[c>>8&0xF];
1539 *lp++ = hex[c>>4&0xF];
1547 lp += runetochar(lp, &rune);
1549 if(c == '\n' || lp >= &line[sizeof(line)-5]) {
1551 write(oflag? 2: 1, line, lp-line);
1569 while(*--s == 'X') {
1570 *s = pid % 10 + '0';
1575 while(access(as, 0) != -1) {