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);
139 if(*argv && (strcmp(*argv, "-") == 0)) {
154 if(p2 >= &savedfile[sizeof(savedfile)])
158 zero = malloc((nlall+5)*sizeof(int*));
159 tfname = mktemp("/tmp/eXXXXX");
184 if(c != ',' && c != ';')
197 if(lastsep != '\n' && a1 == 0)
199 if((addr2=a1) == 0) {
220 rdelete(addr1, addr2);
221 append(gettty, addr1-1);
227 rdelete(addr1, addr2);
235 if(vflag && fchange) {
269 if(c < 'a' || c > 'z')
272 names[c-'a'] = *addr2 & ~01;
315 if((io=open(file, OREAD)) < 0) {
319 if((d = dirfstat(io)) != nil){
320 if(d->mode & DMAPPEND)
321 print("warning: %s is append only\n", file);
324 Binit(&iobuf, io, OREAD);
328 append(getfile, addr2);
336 substitute(globp != 0);
346 if((*addr2&~01) != subnewa)
362 if(temp != 'q' && temp != 'Q') {
368 ((io = open(file, OWRITE)) == -1) ||
369 ((seek(io, 0L, 2)) == -1))
370 if((io = create(file, OWRITE, 0666)) < 0)
372 Binit(&iobuf, io, OWRITE);
377 if(addr1<=zero+1 && addr2==dol)
389 count = addr2 - zero;
419 putshst(getline(*a1++));
420 } while(a1 <= addr2);
430 int sign, *a, opcnt, nextopand, *b, c;
439 } while(c == ' ' || c == '\t');
440 if(c >= '0' && c <= '9') {
455 if(opcnt || c < 'a' || c > 'z')
460 } while(a <= dol && names[c-'a'] != (*a & ~01));
480 if(nextopand == opcnt) {
482 if(a < zero || dol < a)
483 continue; /* error(Q); */
485 if(c != '+' && c != '-' && c != '^') {
499 } while(zero <= a && a <= dol);
512 if(c < '0' || c > '9')
524 addr1 = zero + (dol>zero);
545 if(addr1 < zero+i || addr2 > dol || addr1 > addr2)
555 if(c == '\n' || c == EOF)
557 if(c == 'p' || c == 'l' || c == 'n') {
580 if(c == '\n' || c == EOF) {
582 if(*p1 == 0 && comm != 'f')
591 while((c=getchr()) == ' ')
597 if(p1 >= &file[sizeof(file)-6] || c == ' ' || c == EOF)
600 p1 += runetochar(p1, &rune);
601 } while((c=getchr()) != '\n');
603 if(savedfile[0] == 0 || comm == 'e' || comm == 'f') {
616 if(Bflush(&iobuf) < 0)
644 if(c == '\n' || c == EOF)
669 io = create("ed.hup", OWRITE, 0666);
671 Binit(&iobuf, io, OWRITE);
680 notifyf(void *a, char *s)
682 if(strcmp(s, "interrupt") == 0){
683 if(rescuing || waiting)
688 notejmp(a, savej, 0);
690 if(strcmp(s, "hangup") == 0){
695 fprint(2, "ed: note: %s\n", s);
707 if((lastc=*globp++) != 0)
712 lastc = Bgetrune(&bcons);
738 if(p >= &linebuf[LBSIZE-2])
751 if(linebuf[0] == '.' && linebuf[1] == 0)
764 c = Bgetrune(&iobuf);
767 putst("'\\n' appended");
772 if(lp >= &linebuf[LBSIZE]) {
797 if(Bputrune(&iobuf, '\n') < 0)
801 if(Bputrune(&iobuf, c) < 0)
804 } while(a1 <= addr2);
805 if(Bflush(&iobuf) < 0)
810 append(int (*f)(void), int *a)
812 int *a1, *a2, *rdot, nline, tl;
817 if((dol-zero) >= nlall) {
819 a1 = realloc(zero, (nlall+5)*sizeof(int*));
824 tl = a1 - zero; /* relocate pointers */
846 if(i && (given || dol > zero)) {
852 append(gettty, addr2);
859 static int bformat, bnum; /* 0 */
864 if(peekc == '-' || peekc == '+') {
887 addr1 = addr2-bpagesize;
904 while((c=getchr()) != EOF && c != '\n')
905 if(p < &buf[sizeof(buf) - 6]) {
907 p += runetochar(p, &rune);
912 execl("/bin/rc", "rc", "-c", buf, nil);
913 exits("execl failed");
916 while(waitpid() != pid)
926 if(vflag && fchange && dol!=zero) {
942 rdelete(int *ad1, int *ad2)
966 for(a1=zero; (*a1&01)==0; a1++)
969 for(a2=a1+1; a2<=a3;) {
989 bp = getblock(tl, OREAD);
991 tl &= ~((BLKSIZE/2) - 1);
992 while(*lp++ = *bp++) {
995 bp = getblock(tl += BLKSIZE/2, OREAD);
1011 bp = getblock(tl, OWRITE);
1013 tl &= ~((BLKSIZE/2)-1);
1014 while(*bp = *lp++) {
1023 bp = getblock(tl, OWRITE);
1028 tline += ((lp-linebuf) + 03) & 077776;
1033 blkio(int b, uchar *buf, long (*iofcn)(int, void *, long))
1035 seek(tfile, b*BLKSIZE, 0);
1036 if((*iofcn)(tfile, buf, BLKSIZE) != BLKSIZE) {
1042 getblock(int atl, int iof)
1046 static uchar ibuff[BLKSIZE];
1047 static uchar obuff[BLKSIZE];
1049 bno = atl / (BLKSIZE/2);
1050 off = (atl<<1) & (BLKSIZE-1) & ~03;
1055 nleft = BLKSIZE - off;
1058 return (Rune*)(ibuff+off);
1061 return (Rune*)(obuff+off);
1064 blkio(iblock, ibuff, write);
1067 blkio(bno, ibuff, read);
1068 return (Rune*)(ibuff+off);
1071 blkio(oblock, obuff, write);
1073 return (Rune*)(obuff+off);
1083 for(markp = names; markp < &names[26]; )
1090 if((tfile = create(tfname, ORDWR, 0600)) < 0){
1100 Rune *gp, globuf[GBSIZE];
1106 squeeze(dol > zero);
1112 while((c=getchr()) != '\n') {
1121 if(gp >= &globuf[GBSIZE-2])
1128 for(a1=zero; a1<=dol; a1++) {
1130 if(a1 >= addr1 && a1 <= addr2 && match(a1) == k)
1135 * Special case: g/.../d (avoid n^2 algorithm)
1137 if(globuf[0] == 'd' && globuf[1] == '\n' && globuf[2] == 0) {
1141 for(a1=zero; a1<=dol; a1++) {
1160 for(a1=addr1; a1<=addr2; a1++) {
1163 if(gp++ >= &genbuf[LBSIZE-2])
1168 while(*lp++ = *gp++)
1172 rdelete(addr1+1, addr2);
1177 substitute(int inglob)
1179 int *mp, *a1, nl, gsubf, n;
1181 n = getnum(); /* OK even if n==0 */
1183 for(a1 = addr1; a1 <= addr2; a1++) {
1189 int span = loc2-loc1;
1195 if(span == 0) { /* null RE match */
1204 subnewa = putline();
1207 for(mp=names; mp<&names[26]; mp++)
1214 nl = append(getsub, a1);
1232 if(seof == '\n' || seof == ' ')
1241 if(p >= &rhsbuf[LBSIZE/2])
1244 if(c == '\n' && (!globp || !globp[0])) {
1252 if(p >= &rhsbuf[LBSIZE/2])
1272 if((p2 = linebp) == 0)
1274 while(*p1++ = *p2++)
1293 sp = place(sp, loc1, loc2);
1296 if(c == ESCFLG && (c = *rp++) >= '1' && c < MAXSUB+'0') {
1298 if(subexp[n].rsp && subexp[n].rep) {
1299 sp = place(sp, subexp[n].rsp, subexp[n].rep);
1305 if(sp >= &genbuf[LBSIZE])
1309 loc2 = sp - genbuf + linebuf;
1310 while(*sp++ = *lp++)
1311 if(sp >= &genbuf[LBSIZE])
1315 while(*lp++ = *sp++)
1320 place(Rune *sp, Rune *l1, Rune *l2)
1325 if(sp >= &genbuf[LBSIZE])
1334 int *adt, *ad1, *ad2;
1337 if((adt = address())==0) /* address() guarantees addr is in range */
1344 append(getcopy, ad1++);
1346 delta = zero - ozero;
1351 for(ad1 = addr1; ad1 <= ad2;)
1357 dot = adt + (ad2-ad1);
1375 reverse(int *a1, int *a2)
1404 if((c = getchr()) == '\n') {
1420 if(ep >= expbuf+sizeof(expbuf)) {
1424 ep += runetochar(ep, &c);
1425 if((c = getchr()) == '\n') {
1430 if(ep >= expbuf+sizeof(expbuf)) {
1434 ep += runetochar(ep, &c);
1435 } while((c = getchr()) != eof && c != '\n');
1439 pattern = regcomp(expbuf);
1450 subexp[0].rsp = getline(*addr);
1452 subexp[0].rsp = loc2;
1454 if(rregexec(pattern, linebuf, subexp, MAXSUB)) {
1455 loc1 = subexp[0].rsp;
1456 loc2 = subexp[0].rep;
1483 sp += chartorune(&r, sp);
1511 if(linp != line && linp[-1] == ' ') {
1516 if(col > (72-6-2)) {
1523 if(c=='\b' || c=='\t' || c=='\\') {
1532 if(c<' ' || c>='\177') {
1536 *lp++ = hex[c>>8&0xF];
1537 *lp++ = hex[c>>4&0xF];
1545 lp += runetochar(lp, &rune);
1547 if(c == '\n' || lp >= &line[sizeof(line)-5]) {
1549 write(oflag? 2: 1, line, lp-line);
1567 while(*--s == 'X') {
1568 *s = pid % 10 + '0';
1573 while(access(as, 0) != -1) {