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 = 0xFFFF, /* escape Rune - user defined code */
57 Rune rhsbuf[LBSIZE/2];
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("/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);
375 Blethal(&iobuf, nil);
380 if(addr1<=zero+1 && addr2==dol)
392 count = addr2 - zero;
422 putshst(getline(*a1++));
423 } while(a1 <= addr2);
433 int sign, *a, opcnt, nextopand, *b, c;
442 } while(c == ' ' || c == '\t');
443 if(c >= '0' && c <= '9') {
458 if(opcnt || c < 'a' || c > 'z')
463 } while(a <= dol && names[c-'a'] != (*a & ~01));
483 if(nextopand == opcnt) {
485 if(a < zero || dol < a)
486 continue; /* error(Q); */
488 if(c != '+' && c != '-' && c != '^') {
502 } while(zero <= a && a <= dol);
515 if(c < '0' || c > '9')
527 addr1 = zero + (dol>zero);
548 if(addr1 < zero+i || addr2 > dol || addr1 > addr2)
558 if(c == '\n' || c == EOF)
560 if(c == 'p' || c == 'l' || c == 'n') {
583 if(c == '\n' || c == EOF) {
585 if(*p1 == 0 && comm != 'f')
594 while((c=getchr()) == ' ')
600 if(p1 >= &file[sizeof(file)-6] || c == ' ' || c == EOF)
603 p1 += runetochar(p1, &rune);
604 } while((c=getchr()) != '\n');
606 if(savedfile[0] == 0 || comm == 'e' || comm == 'f') {
619 if(Bflush(&iobuf) < 0)
647 if(c == '\n' || c == EOF)
672 io = create("ed.hup", OWRITE, 0666);
674 Binit(&iobuf, io, OWRITE);
675 Blethal(&iobuf, nil);
684 notifyf(void *a, char *s)
686 if(strcmp(s, "interrupt") == 0){
687 if(rescuing || waiting)
692 notejmp(a, savej, 0);
694 if(strcmp(s, "hangup") == 0){
699 fprint(2, "ed: note: %s\n", s);
711 if((lastc=*globp++) != 0)
716 lastc = Bgetrune(&bcons);
742 if(p >= &linebuf[LBSIZE-2])
755 if(linebuf[0] == '.' && linebuf[1] == 0)
768 c = Bgetrune(&iobuf);
771 putst("'\\n' appended");
776 if(lp >= &linebuf[LBSIZE]) {
801 if(Bputrune(&iobuf, '\n') < 0)
805 if(Bputrune(&iobuf, c) < 0)
808 } while(a1 <= addr2);
809 if(Bflush(&iobuf) < 0)
814 append(int (*f)(void), int *a)
816 int *a1, *a2, *rdot, nline, tl;
821 if((dol-zero) >= nlall) {
823 a1 = realloc(zero, (nlall+5)*sizeof(int*));
828 tl = a1 - zero; /* relocate pointers */
850 if(i && (given || dol > zero)) {
856 append(gettty, addr2);
863 static int bformat, bnum; /* 0 */
868 if(peekc == '-' || peekc == '+') {
891 addr1 = addr2-bpagesize;
908 while((c=getchr()) != EOF && c != '\n')
909 if(p < &buf[sizeof(buf) - 6]) {
911 p += runetochar(p, &rune);
916 execl("/bin/rc", "rc", "-c", buf, nil);
917 exits("execl failed");
920 while(waitpid() != pid)
930 if(vflag && fchange && dol!=zero) {
946 rdelete(int *ad1, int *ad2)
970 for(a1=zero; (*a1&01)==0; a1++)
973 for(a2=a1+1; a2<=a3;) {
993 bp = getblock(tl, OREAD);
995 tl &= ~((BLKSIZE/2) - 1);
996 while(*lp++ = *bp++) {
999 bp = getblock(tl += BLKSIZE/2, OREAD);
1015 bp = getblock(tl, OWRITE);
1017 tl &= ~((BLKSIZE/2)-1);
1018 while(*bp = *lp++) {
1027 bp = getblock(tl, OWRITE);
1032 tline += ((lp-linebuf) + 03) & 077776;
1037 blkio(int b, uchar *buf, long (*iofcn)(int, void *, long))
1039 seek(tfile, b*BLKSIZE, 0);
1040 if((*iofcn)(tfile, buf, BLKSIZE) != BLKSIZE) {
1046 getblock(int atl, int iof)
1050 static uchar ibuff[BLKSIZE];
1051 static uchar obuff[BLKSIZE];
1053 bno = atl / (BLKSIZE/2);
1054 off = (atl<<1) & (BLKSIZE-1) & ~03;
1059 nleft = BLKSIZE - off;
1062 return (Rune*)(ibuff+off);
1065 return (Rune*)(obuff+off);
1068 blkio(iblock, ibuff, write);
1071 blkio(bno, ibuff, read);
1072 return (Rune*)(ibuff+off);
1075 blkio(oblock, obuff, write);
1077 return (Rune*)(obuff+off);
1087 for(markp = names; markp < &names[26]; )
1094 if((tfile = create(tfname, ORDWR, 0600)) < 0){
1104 Rune *gp, globuf[GBSIZE];
1110 squeeze(dol > zero);
1116 while((c=getchr()) != '\n') {
1125 if(gp >= &globuf[GBSIZE-2])
1132 for(a1=zero; a1<=dol; a1++) {
1134 if(a1 >= addr1 && a1 <= addr2 && match(a1) == k)
1139 * Special case: g/.../d (avoid n^2 algorithm)
1141 if(globuf[0] == 'd' && globuf[1] == '\n' && globuf[2] == 0) {
1145 for(a1=zero; a1<=dol; a1++) {
1164 for(a1=addr1; a1<=addr2; a1++) {
1167 if(gp++ >= &genbuf[LBSIZE-2])
1172 while(*lp++ = *gp++)
1176 rdelete(addr1+1, addr2);
1181 substitute(int inglob)
1183 int *mp, *a1, nl, gsubf, n;
1185 n = getnum(); /* OK even if n==0 */
1187 for(a1 = addr1; a1 <= addr2; a1++) {
1193 int span = loc2-loc1;
1199 if(span == 0) { /* null RE match */
1208 subnewa = putline();
1211 for(mp=names; mp<&names[26]; mp++)
1218 nl = append(getsub, a1);
1236 if(seof == '\n' || seof == ' ')
1245 if(p >= &rhsbuf[LBSIZE/2])
1248 if(c == '\n' && (!globp || !globp[0])) {
1256 if(p >= &rhsbuf[LBSIZE/2])
1276 if((p2 = linebp) == 0)
1278 while(*p1++ = *p2++)
1297 sp = place(sp, loc1, loc2);
1300 if(c == ESCFLG && (c = *rp++) >= '1' && c < MAXSUB+'0') {
1302 if(subexp[n].rsp && subexp[n].rep) {
1303 sp = place(sp, subexp[n].rsp, subexp[n].rep);
1309 if(sp >= &genbuf[LBSIZE])
1313 loc2 = sp - genbuf + linebuf;
1314 while(*sp++ = *lp++)
1315 if(sp >= &genbuf[LBSIZE])
1319 while(*lp++ = *sp++)
1324 place(Rune *sp, Rune *l1, Rune *l2)
1329 if(sp >= &genbuf[LBSIZE])
1338 int *adt, *ad1, *ad2;
1341 if((adt = address())==0) /* address() guarantees addr is in range */
1348 append(getcopy, ad1++);
1350 delta = zero - ozero;
1355 for(ad1 = addr1; ad1 <= ad2;)
1361 dot = adt + (ad2-ad1);
1379 reverse(int *a1, int *a2)
1408 if((c = getchr()) == '\n') {
1424 if(ep >= expbuf+sizeof(expbuf)) {
1428 ep += runetochar(ep, &c);
1429 if((c = getchr()) == '\n') {
1434 if(ep >= expbuf+sizeof(expbuf)) {
1438 ep += runetochar(ep, &c);
1439 } while((c = getchr()) != eof && c != '\n');
1443 pattern = regcomp(expbuf);
1454 subexp[0].rsp = getline(*addr);
1456 subexp[0].rsp = loc2;
1458 if(rregexec(pattern, linebuf, subexp, MAXSUB)) {
1459 loc1 = subexp[0].rsp;
1460 loc2 = subexp[0].rep;
1487 sp += chartorune(&r, sp);
1515 if(linp != line && linp[-1] == ' ') {
1520 if(col > (72-6-2)) {
1527 if(c=='\b' || c=='\t' || c=='\\') {
1536 if(c<' ' || c>='\177') {
1540 *lp++ = hex[c>>8&0xF];
1541 *lp++ = hex[c>>4&0xF];
1549 lp += runetochar(lp, &rune);
1551 if(c == '\n' || lp >= &line[sizeof(line)-5]) {
1553 write(oflag? 2: 1, line, lp-line);
1571 while(*--s == 'X') {
1572 *s = pid % 10 + '0';
1577 while(access(as, 0) != -1) {