diff options
author | rsc <devnull@localhost> | 2003-11-23 18:04:47 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2003-11-23 18:04:47 +0000 |
commit | bc7cb1a15a67c859c8c71c4b52bb35fe9425a63d (patch) | |
tree | 8ca0fe4e2418e6aa18dc74a236c577a719f6c6ed /src/cmd/ed.c | |
parent | f08fdedcee12c06e3ce9ac9bec363915978e8289 (diff) | |
download | plan9port-bc7cb1a15a67c859c8c71c4b52bb35fe9425a63d.tar.gz plan9port-bc7cb1a15a67c859c8c71c4b52bb35fe9425a63d.tar.bz2 plan9port-bc7cb1a15a67c859c8c71c4b52bb35fe9425a63d.zip |
new utilities.
the .C files compile but are renamed to avoid building automatically.
Diffstat (limited to 'src/cmd/ed.c')
-rw-r--r-- | src/cmd/ed.c | 1608 |
1 files changed, 1608 insertions, 0 deletions
diff --git a/src/cmd/ed.c b/src/cmd/ed.c new file mode 100644 index 00000000..42fa3e07 --- /dev/null +++ b/src/cmd/ed.c @@ -0,0 +1,1608 @@ +/* + * Editor + */ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <regexp.h> + +enum +{ + FNSIZE = 128, /* file name */ + LBSIZE = 4096, /* max line size */ + BLKSIZE = 4096, /* block size in temp file */ + NBLK = 8191, /* max size of temp file */ + ESIZE = 256, /* max size of reg exp */ + GBSIZE = 256, /* max size of global command */ + MAXSUB = 9, /* max number of sub reg exp */ + ESCFLG = 0xFFFF, /* escape Rune - user defined code */ + EOF = -1, +}; + +void (*oldhup)(int); +void (*oldquit)(int); +int* addr1; +int* addr2; +int anymarks; +int col; +long count; +int* dol; +int* dot; +int fchange; +char file[FNSIZE]; +Rune genbuf[LBSIZE]; +int given; +Rune* globp; +int iblock; +int ichanged; +int io; +Biobuf iobuf; +int lastc; +char line[70]; +Rune* linebp; +Rune linebuf[LBSIZE]; +int listf; +int listn; +Rune* loc1; +Rune* loc2; +int names[26]; +int nleft; +int oblock; +int oflag; +Reprog *pattern; +int peekc; +int pflag; +int rescuing; +Rune rhsbuf[LBSIZE/2]; +char savedfile[FNSIZE]; +jmp_buf savej; +int subnewa; +int subolda; +Resub subexp[MAXSUB]; +char* tfname; +int tline; +int waiting; +int wrapp; +int* zero; + +char Q[] = ""; +char T[] = "TMP"; +char WRERR[] = "WRITE ERROR"; +int bpagesize = 20; +char hex[] = "0123456789abcdef"; +char* linp = line; +ulong nlall = 128; +int tfile = -1; +int vflag = 1; + +void add(int); +int* address(void); +int append(int(*)(void), int*); +void browse(void); +void callunix(void); +void commands(void); +void compile(int); +int compsub(void); +void dosub(void); +void error(char*); +int match(int*); +void exfile(int); +void filename(int); +Rune* getblock(int, int); +int getchr(void); +int getcopy(void); +int getfile(void); +Rune* getline(int); +int getnum(void); +int getsub(void); +int gettty(void); +void global(int); +void init(void); +void join(void); +void move(int); +void newline(void); +void nonzero(void); +void notifyf(void*, char*); +Rune* place(Rune*, Rune*, Rune*); +void printcom(void); +void putchr(int); +void putd(void); +void putfile(void); +int putline(void); +void putshst(Rune*); +void putst(char*); +void quit(void); +void rdelete(int*, int*); +void regerror(char *); +void reverse(int*, int*); +void setnoaddr(void); +void setwide(void); +void squeeze(int); +void substitute(int); + +Rune La[] = { 'a', 0 }; +Rune Lr[] = { 'r', 0 }; + +char tmp[] = "/tmp/eXXXXX"; + +void +main(int argc, char *argv[]) +{ + char *p1, *p2; + + notify(notifyf); + ARGBEGIN { + case 'o': + oflag = 1; + vflag = 0; + break; + } ARGEND + + USED(argc); + if(*argv && (strcmp(*argv, "-") == 0)) { + argv++; + vflag = 0; + } + if(oflag) { + p1 = "/fd/1"; + p2 = savedfile; + while(*p2++ = *p1++) + ; + globp = La; + } else + if(*argv) { + p1 = *argv; + p2 = savedfile; + while(*p2++ = *p1++) + if(p2 >= &savedfile[sizeof(savedfile)]) + p2--; + globp = Lr; + } + zero = malloc((nlall+5)*sizeof(int*)); + tfname = mktemp(tmp); + init(); + setjmp(savej); + commands(); + quit(); +} + +void +commands(void) +{ + int *a1, c, temp; + char lastsep; + Dir *d; + + for(;;) { + if(pflag) { + pflag = 0; + addr1 = addr2 = dot; + printcom(); + } + c = '\n'; + for(addr1 = 0;;) { + lastsep = c; + a1 = address(); + c = getchr(); + if(c != ',' && c != ';') + break; + if(lastsep == ',') + error(Q); + if(a1 == 0) { + a1 = zero+1; + if(a1 > dol) + a1--; + } + addr1 = a1; + if(c == ';') + dot = a1; + } + if(lastsep != '\n' && a1 == 0) + a1 = dol; + if((addr2=a1) == 0) { + given = 0; + addr2 = dot; + } else + given = 1; + if(addr1 == 0) + addr1 = addr2; + switch(c) { + + case 'a': + add(0); + continue; + + case 'b': + nonzero(); + browse(); + continue; + + case 'c': + nonzero(); + newline(); + rdelete(addr1, addr2); + append(gettty, addr1-1); + continue; + + case 'd': + nonzero(); + newline(); + rdelete(addr1, addr2); + continue; + + case 'E': + fchange = 0; + c = 'e'; + case 'e': + setnoaddr(); + if(vflag && fchange) { + fchange = 0; + error(Q); + } + filename(c); + init(); + addr2 = zero; + goto caseread; + + case 'f': + setnoaddr(); + filename(c); + putst(savedfile); + continue; + + case 'g': + global(1); + continue; + + case 'i': + add(-1); + continue; + + + case 'j': + if(!given) + addr2++; + newline(); + join(); + continue; + + case 'k': + nonzero(); + c = getchr(); + if(c < 'a' || c > 'z') + error(Q); + newline(); + names[c-'a'] = *addr2 & ~01; + anymarks |= 01; + continue; + + case 'm': + move(0); + continue; + + case 'n': + listn++; + newline(); + printcom(); + continue; + + case '\n': + if(a1==0) { + a1 = dot+1; + addr2 = a1; + addr1 = a1; + } + if(lastsep==';') + addr1 = a1; + printcom(); + continue; + + case 'l': + listf++; + case 'p': + case 'P': + newline(); + printcom(); + continue; + + case 'Q': + fchange = 0; + case 'q': + setnoaddr(); + newline(); + quit(); + + case 'r': + filename(c); + caseread: + if((io=open(file, OREAD)) < 0) { + lastc = '\n'; + error(file); + } + if((d = dirfstat(io)) != nil){ + if(d->mode & DMAPPEND) + print("warning: %s is append only\n", file); + free(d); + } + Binit(&iobuf, io, OREAD); + setwide(); + squeeze(0); + c = zero != dol; + append(getfile, addr2); + exfile(OREAD); + + fchange = c; + continue; + + case 's': + nonzero(); + substitute(globp != 0); + continue; + + case 't': + move(1); + continue; + + case 'u': + nonzero(); + newline(); + if((*addr2&~01) != subnewa) + error(Q); + *addr2 = subolda; + dot = addr2; + continue; + + case 'v': + global(0); + continue; + + case 'W': + wrapp++; + case 'w': + setwide(); + squeeze(dol>zero); + temp = getchr(); + if(temp != 'q' && temp != 'Q') { + peekc = temp; + temp = 0; + } + filename(c); + if(!wrapp || + ((io = open(file, OWRITE)) == -1) || + ((seek(io, 0L, 2)) == -1)) + if((io = create(file, OWRITE, 0666)) < 0) + error(file); + Binit(&iobuf, io, OWRITE); + wrapp = 0; + if(dol > zero) + putfile(); + exfile(OWRITE); + if(addr1<=zero+1 && addr2==dol) + fchange = 0; + if(temp == 'Q') + fchange = 0; + if(temp) + quit(); + continue; + + case '=': + setwide(); + squeeze(0); + newline(); + count = addr2 - zero; + putd(); + putchr(L'\n'); + continue; + + case '!': + callunix(); + continue; + + case EOF: + return; + + } + error(Q); + } +} + +void +printcom(void) +{ + int *a1; + + nonzero(); + a1 = addr1; + do { + if(listn) { + count = a1-zero; + putd(); + putchr(L'\t'); + } + putshst(getline(*a1++)); + } while(a1 <= addr2); + dot = addr2; + listf = 0; + listn = 0; + pflag = 0; +} + +int* +address(void) +{ + int sign, *a, opcnt, nextopand, *b, c; + + nextopand = -1; + sign = 1; + opcnt = 0; + a = dot; + do { + do { + c = getchr(); + } while(c == ' ' || c == '\t'); + if(c >= '0' && c <= '9') { + peekc = c; + if(!opcnt) + a = zero; + a += sign*getnum(); + } else + switch(c) { + case '$': + a = dol; + case '.': + if(opcnt) + error(Q); + break; + case '\'': + c = getchr(); + if(opcnt || c < 'a' || c > 'z') + error(Q); + a = zero; + do { + a++; + } while(a <= dol && names[c-'a'] != (*a & ~01)); + break; + case '?': + sign = -sign; + case '/': + compile(c); + b = a; + for(;;) { + a += sign; + if(a <= zero) + a = dol; + if(a > dol) + a = zero; + if(match(a)) + break; + if(a == b) + error(Q); + } + break; + default: + if(nextopand == opcnt) { + a += sign; + if(a < zero || dol < a) + continue; /* error(Q); */ + } + if(c != '+' && c != '-' && c != '^') { + peekc = c; + if(opcnt == 0) + a = 0; + return a; + } + sign = 1; + if(c != '+') + sign = -sign; + nextopand = ++opcnt; + continue; + } + sign = 1; + opcnt++; + } while(zero <= a && a <= dol); + error(Q); + return 0; +} + +int +getnum(void) +{ + int r, c; + + r = 0; + for(;;) { + c = getchr(); + if(c < '0' || c > '9') + break; + r = r*10 + (c-'0'); + } + peekc = c; + return r; +} + +void +setwide(void) +{ + if(!given) { + addr1 = zero + (dol>zero); + addr2 = dol; + } +} + +void +setnoaddr(void) +{ + if(given) + error(Q); +} + +void +nonzero(void) +{ + squeeze(1); +} + +void +squeeze(int i) +{ + if(addr1 < zero+i || addr2 > dol || addr1 > addr2) + error(Q); +} + +void +newline(void) +{ + int c; + + c = getchr(); + if(c == '\n' || c == EOF) + return; + if(c == 'p' || c == 'l' || c == 'n') { + pflag++; + if(c == 'l') + listf++; + else + if(c == 'n') + listn++; + c = getchr(); + if(c == '\n') + return; + } + error(Q); +} + +void +filename(int comm) +{ + char *p1, *p2; + Rune rune; + int c; + + count = 0; + c = getchr(); + if(c == '\n' || c == EOF) { + p1 = savedfile; + if(*p1 == 0 && comm != 'f') + error(Q); + p2 = file; + while(*p2++ = *p1++) + ; + return; + } + if(c != ' ') + error(Q); + while((c=getchr()) == ' ') + ; + if(c == '\n') + error(Q); + p1 = file; + do { + if(p1 >= &file[sizeof(file)-6] || c == ' ' || c == EOF) + error(Q); + rune = c; + p1 += runetochar(p1, &rune); + } while((c=getchr()) != '\n'); + *p1 = 0; + if(savedfile[0] == 0 || comm == 'e' || comm == 'f') { + p1 = savedfile; + p2 = file; + while(*p1++ = *p2++) + ; + } +} + +void +exfile(int om) +{ + + if(om == OWRITE) + if(Bflush(&iobuf) < 0) + error(Q); + close(io); + io = -1; + if(vflag) { + putd(); + putchr(L'\n'); + } +} + +void +error1(char *s) +{ + int c; + + wrapp = 0; + listf = 0; + listn = 0; + count = 0; + seek(0, 0, 2); + pflag = 0; + if(globp) + lastc = '\n'; + globp = 0; + peekc = lastc; + if(lastc) + for(;;) { + c = getchr(); + if(c == '\n' || c == EOF) + break; + } + if(io > 0) { + close(io); + io = -1; + } + putchr(L'?'); + putst(s); +} + +void +error(char *s) +{ + error1(s); + longjmp(savej, 1); +} + +void +rescue(void) +{ + rescuing = 1; + if(dol > zero) { + addr1 = zero+1; + addr2 = dol; + io = create("ed.hup", OWRITE, 0666); + if(io > 0){ + Binit(&iobuf, io, OWRITE); + putfile(); + } + } + fchange = 0; + quit(); +} + +void +notifyf(void *a, char *s) +{ + if(strcmp(s, "interrupt") == 0){ + if(rescuing || waiting) + noted(NCONT); + putchr(L'\n'); + lastc = '\n'; + error1(Q); + notejmp(a, savej, 0); + } + if(strcmp(s, "hangup") == 0){ + if(rescuing) + noted(NDFLT); + rescue(); + } + fprint(2, "ed: note: %s\n", s); + abort(); +} + +int +getchr(void) +{ + char s[UTFmax]; + int i; + Rune r; + + if(lastc = peekc) { + peekc = 0; + return lastc; + } + if(globp) { + if((lastc=*globp++) != 0) + return lastc; + globp = 0; + return EOF; + } + for(i=0;;) { + if(read(0, s+i, 1) <= 0) + return lastc = EOF; + i++; + if(fullrune(s, i)) + break; + + } + chartorune(&r, s); + lastc = r; + return lastc; +} + +int +gety(void) +{ + int c; + Rune *gf, *p; + + p = linebuf; + gf = globp; + for(;;) { + c = getchr(); + if(c == '\n') { + *p = 0; + return 0; + } + if(c == EOF) { + if(gf) + peekc = c; + return c; + } + if(c == 0) + continue; + *p++ = c; + if(p >= &linebuf[LBSIZE-2]) + error(Q); + } + return 0; +} + +int +gettty(void) +{ + int rc; + + rc = gety(); + if(rc) + return rc; + if(linebuf[0] == '.' && linebuf[1] == 0) + return EOF; + return 0; +} + +int +getfile(void) +{ + int c; + Rune *lp; + + lp = linebuf; + do { + c = Bgetrune(&iobuf); + if(c < 0) { + if(lp > linebuf) { + putst("'\\n' appended"); + c = '\n'; + } else + return EOF; + } + if(lp >= &linebuf[LBSIZE]) { + lastc = '\n'; + error(Q); + } + *lp++ = c; + count++; + } while(c != '\n'); + lp[-1] = 0; + return 0; +} + +void +putfile(void) +{ + int *a1; + Rune *lp; + long c; + + a1 = addr1; + do { + lp = getline(*a1++); + for(;;) { + count++; + c = *lp++; + if(c == 0) { + if(Bputrune(&iobuf, '\n') < 0) + error(Q); + break; + } + if(Bputrune(&iobuf, c) < 0) + error(Q); + } + } while(a1 <= addr2); + if(Bflush(&iobuf) < 0) + error(Q); +} + +int +append(int (*f)(void), int *a) +{ + int *a1, *a2, *rdot, nline, tl; + + nline = 0; + dot = a; + while((*f)() == 0) { + if((dol-zero) >= nlall) { + nlall += 512; + a1 = realloc(zero, (nlall+5)*sizeof(int*)); + if(a1 == 0) { + error("MEM?"); + rescue(); + } + tl = a1 - zero; /* relocate pointers */ + zero += tl; + addr1 += tl; + addr2 += tl; + dol += tl; + dot += tl; + } + tl = putline(); + nline++; + a1 = ++dol; + a2 = a1+1; + rdot = ++dot; + while(a1 > rdot) + *--a2 = *--a1; + *rdot = tl; + } + return nline; +} + +void +add(int i) +{ + if(i && (given || dol > zero)) { + addr1--; + addr2--; + } + squeeze(0); + newline(); + append(gettty, addr2); +} + +void +browse(void) +{ + int forward, n; + static int bformat, bnum; /* 0 */ + + forward = 1; + peekc = getchr(); + if(peekc != '\n'){ + if(peekc == '-' || peekc == '+') { + if(peekc == '-') + forward = 0; + getchr(); + } + n = getnum(); + if(n > 0) + bpagesize = n; + } + newline(); + if(pflag) { + bformat = listf; + bnum = listn; + } else { + listf = bformat; + listn = bnum; + } + if(forward) { + addr1 = addr2; + addr2 += bpagesize; + if(addr2 > dol) + addr2 = dol; + } else { + addr1 = addr2-bpagesize; + if(addr1 <= zero) + addr1 = zero+1; + } + printcom(); +} + +void +callunix(void) +{ + int c, pid; + Rune rune; + char buf[512]; + char *p; + + setnoaddr(); + p = buf; + while((c=getchr()) != EOF && c != '\n') + if(p < &buf[sizeof(buf) - 6]) { + rune = c; + p += runetochar(p, &rune); + } + *p = 0; + pid = fork(); + if(pid == 0) { + execl("/bin/rc", "rc", "-c", buf, 0); + exits("execl failed"); + } + waiting = 1; + while(waitpid() != pid) + ; + waiting = 0; + if(vflag) + putst("!"); +} + +void +quit(void) +{ + if(vflag && fchange && dol!=zero) { + fchange = 0; + error(Q); + } + remove(tfname); + exits(0); +} + +void +onquit(int sig) +{ + USED(sig); + quit(); +} + +void +rdelete(int *ad1, int *ad2) +{ + int *a1, *a2, *a3; + + a1 = ad1; + a2 = ad2+1; + a3 = dol; + dol -= a2 - a1; + do { + *a1++ = *a2++; + } while(a2 <= a3); + a1 = ad1; + if(a1 > dol) + a1 = dol; + dot = a1; + fchange = 1; +} + +void +gdelete(void) +{ + int *a1, *a2, *a3; + + a3 = dol; + for(a1=zero; (*a1&01)==0; a1++) + if(a1>=a3) + return; + for(a2=a1+1; a2<=a3;) { + if(*a2 & 01) { + a2++; + dot = a1; + } else + *a1++ = *a2++; + } + dol = a1-1; + if(dot > dol) + dot = dol; + fchange = 1; +} + +Rune* +getline(int tl) +{ + Rune *lp, *bp; + int nl; + + lp = linebuf; + bp = getblock(tl, OREAD); + nl = nleft; + tl &= ~((BLKSIZE/2) - 1); + while(*lp++ = *bp++) { + nl -= sizeof(Rune); + if(nl == 0) { + bp = getblock(tl += BLKSIZE/2, OREAD); + nl = nleft; + } + } + return linebuf; +} + +int +putline(void) +{ + Rune *lp, *bp; + int nl, tl; + + fchange = 1; + lp = linebuf; + tl = tline; + bp = getblock(tl, OWRITE); + nl = nleft; + tl &= ~((BLKSIZE/2)-1); + while(*bp = *lp++) { + if(*bp++ == '\n') { + bp[-1] = 0; + linebp = lp; + break; + } + nl -= sizeof(Rune); + if(nl == 0) { + tl += BLKSIZE/2; + bp = getblock(tl, OWRITE); + nl = nleft; + } + } + nl = tline; + tline += ((lp-linebuf) + 03) & 077776; + return nl; +} + +void +blkio(int b, uchar *buf, int isread) +{ + int n; + + seek(tfile, b*BLKSIZE, 0); + if(isread) + n = read(tfile, buf, BLKSIZE); + else + n = write(tfile, buf, BLKSIZE); + if(n != BLKSIZE) + error(T); +} + +Rune* +getblock(int atl, int iof) +{ + int bno, off; + + static uchar ibuff[BLKSIZE]; + static uchar obuff[BLKSIZE]; + + bno = atl / (BLKSIZE/2); + off = (atl<<1) & (BLKSIZE-1) & ~03; + if(bno >= NBLK) { + lastc = '\n'; + error(T); + } + nleft = BLKSIZE - off; + if(bno == iblock) { + ichanged |= iof; + return (Rune*)(ibuff+off); + } + if(bno == oblock) + return (Rune*)(obuff+off); + if(iof == OREAD) { + if(ichanged) + blkio(iblock, ibuff, 0); + ichanged = 0; + iblock = bno; + blkio(bno, ibuff, 1); + return (Rune*)(ibuff+off); + } + if(oblock >= 0) + blkio(oblock, obuff, 0); + oblock = bno; + return (Rune*)(obuff+off); +} + +void +init(void) +{ + int *markp; + + close(tfile); + tline = 2; + for(markp = names; markp < &names[26]; ) + *markp++ = 0; + subnewa = 0; + anymarks = 0; + iblock = -1; + oblock = -1; + ichanged = 0; + if((tfile = create(tfname, ORDWR, 0600)) < 0){ + error1(T); + exits(0); + } + dot = dol = zero; +} + +void +global(int k) +{ + Rune *gp, globuf[GBSIZE]; + int c, *a1; + + if(globp) + error(Q); + setwide(); + squeeze(dol > zero); + c = getchr(); + if(c == '\n') + error(Q); + compile(c); + gp = globuf; + while((c=getchr()) != '\n') { + if(c == EOF) + error(Q); + if(c == '\\') { + c = getchr(); + if(c != '\n') + *gp++ = '\\'; + } + *gp++ = c; + if(gp >= &globuf[GBSIZE-2]) + error(Q); + } + if(gp == globuf) + *gp++ = 'p'; + *gp++ = '\n'; + *gp = 0; + for(a1=zero; a1<=dol; a1++) { + *a1 &= ~01; + if(a1 >= addr1 && a1 <= addr2 && match(a1) == k) + *a1 |= 01; + } + + /* + * Special case: g/.../d (avoid n^2 algorithm) + */ + if(globuf[0] == 'd' && globuf[1] == '\n' && globuf[2] == 0) { + gdelete(); + return; + } + for(a1=zero; a1<=dol; a1++) { + if(*a1 & 01) { + *a1 &= ~01; + dot = a1; + globp = globuf; + commands(); + a1 = zero; + } + } +} + +void +join(void) +{ + Rune *gp, *lp; + int *a1; + + nonzero(); + gp = genbuf; + for(a1=addr1; a1<=addr2; a1++) { + lp = getline(*a1); + while(*gp = *lp++) + if(gp++ >= &genbuf[LBSIZE-2]) + error(Q); + } + lp = linebuf; + gp = genbuf; + while(*lp++ = *gp++) + ; + *addr1 = putline(); + if(addr1 < addr2) + rdelete(addr1+1, addr2); + dot = addr1; +} + +void +substitute(int inglob) +{ + int *mp, *a1, nl, gsubf, n; + + n = getnum(); /* OK even if n==0 */ + gsubf = compsub(); + for(a1 = addr1; a1 <= addr2; a1++) { + if(match(a1)){ + int *ozero; + int m = n; + + do { + int span = loc2-loc1; + + if(--m <= 0) { + dosub(); + if(!gsubf) + break; + if(span == 0) { /* null RE match */ + if(*loc2 == 0) + break; + loc2++; + } + } + } while(match(0)); + if(m <= 0) { + inglob |= 01; + subnewa = putline(); + *a1 &= ~01; + if(anymarks) { + for(mp=names; mp<&names[26]; mp++) + if(*mp == *a1) + *mp = subnewa; + } + subolda = *a1; + *a1 = subnewa; + ozero = zero; + nl = append(getsub, a1); + addr2 += nl; + nl += zero-ozero; + a1 += nl; + } + } + } + if(inglob == 0) + error(Q); +} + +int +compsub(void) +{ + int seof, c; + Rune *p; + + seof = getchr(); + if(seof == '\n' || seof == ' ') + error(Q); + compile(seof); + p = rhsbuf; + for(;;) { + c = getchr(); + if(c == '\\') { + c = getchr(); + *p++ = ESCFLG; + if(p >= &rhsbuf[LBSIZE/2]) + error(Q); + } else + if(c == '\n' && (!globp || !globp[0])) { + peekc = c; + pflag++; + break; + } else + if(c == seof) + break; + *p++ = c; + if(p >= &rhsbuf[LBSIZE/2]) + error(Q); + } + *p = 0; + peekc = getchr(); + if(peekc == 'g') { + peekc = 0; + newline(); + return 1; + } + newline(); + return 0; +} + +int +getsub(void) +{ + Rune *p1, *p2; + + p1 = linebuf; + if((p2 = linebp) == 0) + return EOF; + while(*p1++ = *p2++) + ; + linebp = 0; + return 0; +} + +void +dosub(void) +{ + Rune *lp, *sp, *rp; + int c, n; + + lp = linebuf; + sp = genbuf; + rp = rhsbuf; + while(lp < loc1) + *sp++ = *lp++; + while(c = *rp++) { + if(c == '&'){ + sp = place(sp, loc1, loc2); + continue; + } + if(c == ESCFLG && (c = *rp++) >= '1' && c < MAXSUB+'0') { + n = c-'0'; + if(subexp[n].s.rsp && subexp[n].e.rep) { + sp = place(sp, subexp[n].s.rsp, subexp[n].e.rep); + continue; + } + error(Q); + } + *sp++ = c; + if(sp >= &genbuf[LBSIZE]) + error(Q); + } + lp = loc2; + loc2 = sp - genbuf + linebuf; + while(*sp++ = *lp++) + if(sp >= &genbuf[LBSIZE]) + error(Q); + lp = linebuf; + sp = genbuf; + while(*lp++ = *sp++) + ; +} + +Rune* +place(Rune *sp, Rune *l1, Rune *l2) +{ + + while(l1 < l2) { + *sp++ = *l1++; + if(sp >= &genbuf[LBSIZE]) + error(Q); + } + return sp; +} + +void +move(int cflag) +{ + int *adt, *ad1, *ad2; + + nonzero(); + if((adt = address())==0) /* address() guarantees addr is in range */ + error(Q); + newline(); + if(cflag) { + int *ozero, delta; + ad1 = dol; + ozero = zero; + append(getcopy, ad1++); + ad2 = dol; + delta = zero - ozero; + ad1 += delta; + adt += delta; + } else { + ad2 = addr2; + for(ad1 = addr1; ad1 <= ad2;) + *ad1++ &= ~01; + ad1 = addr1; + } + ad2++; + if(adt<ad1) { + dot = adt + (ad2-ad1); + if((++adt)==ad1) + return; + reverse(adt, ad1); + reverse(ad1, ad2); + reverse(adt, ad2); + } else + if(adt >= ad2) { + dot = adt++; + reverse(ad1, ad2); + reverse(ad2, adt); + reverse(ad1, adt); + } else + error(Q); + fchange = 1; +} + +void +reverse(int *a1, int *a2) +{ + int t; + + for(;;) { + t = *--a2; + if(a2 <= a1) + return; + *a2 = *a1; + *a1++ = t; + } +} + +int +getcopy(void) +{ + if(addr1 > addr2) + return EOF; + getline(*addr1++); + return 0; +} + +void +compile(int eof) +{ + Rune c; + char *ep; + char expbuf[ESIZE]; + + if((c = getchr()) == '\n') { + peekc = c; + c = eof; + } + if(c == eof) { + if(!pattern) + error(Q); + return; + } + if(pattern) { + free(pattern); + pattern = 0; + } + ep = expbuf; + do { + if(c == '\\') { + if(ep >= expbuf+sizeof(expbuf)) { + error(Q); + return; + } + ep += runetochar(ep, &c); + if((c = getchr()) == '\n') { + error(Q); + return; + } + } + if(ep >= expbuf+sizeof(expbuf)) { + error(Q); + return; + } + ep += runetochar(ep, &c); + } while((c = getchr()) != eof && c != '\n'); + if(c == '\n') + peekc = c; + *ep = 0; + pattern = regcomp(expbuf); +} + +int +match(int *addr) +{ + if(!pattern) + return 0; + if(addr){ + if(addr == zero) + return 0; + subexp[0].s.rsp = getline(*addr); + } else + subexp[0].s.rsp = loc2; + subexp[0].e.rep = 0; + if(rregexec(pattern, linebuf, subexp, MAXSUB)) { + loc1 = subexp[0].s.rsp; + loc2 = subexp[0].e.rep; + return 1; + } + loc1 = loc2 = 0; + return 0; + +} + +void +putd(void) +{ + int r; + + r = count%10; + count /= 10; + if(count) + putd(); + putchr(r + L'0'); +} + +void +putst(char *sp) +{ + Rune r; + + col = 0; + for(;;) { + sp += chartorune(&r, sp); + if(r == 0) + break; + putchr(r); + } + putchr(L'\n'); +} + +void +putshst(Rune *sp) +{ + col = 0; + while(*sp) + putchr(*sp++); + putchr(L'\n'); +} + +void +putchr(int ac) +{ + char *lp; + int c; + Rune rune; + + lp = linp; + c = ac; + if(listf) { + if(c == '\n') { + if(linp != line && linp[-1] == ' ') { + *lp++ = '\\'; + *lp++ = 'n'; + } + } else { + if(col > (72-6-2)) { + col = 8; + *lp++ = '\\'; + *lp++ = '\n'; + *lp++ = '\t'; + } + col++; + if(c=='\b' || c=='\t' || c=='\\') { + *lp++ = '\\'; + if(c == '\b') + c = 'b'; + else + if(c == '\t') + c = 't'; + col++; + } else + if(c<' ' || c>='\177') { + *lp++ = '\\'; + *lp++ = 'x'; + *lp++ = hex[c>>12]; + *lp++ = hex[c>>8&0xF]; + *lp++ = hex[c>>4&0xF]; + c = hex[c&0xF]; + col += 5; + } + } + } + + rune = c; + lp += runetochar(lp, &rune); + + if(c == '\n' || lp >= &line[sizeof(line)-5]) { + linp = line; + write(oflag? 2: 1, line, lp-line); + return; + } + linp = lp; +} + +char* +mktemp(char *as) +{ + char *s; + unsigned pid; + int i; + + pid = getpid(); + s = as; + while(*s++) + ; + s--; + while(*--s == 'X') { + *s = pid % 10 + '0'; + pid /= 10; + } + s++; + i = 'a'; + while(access(as, 0) != -1) { + if(i == 'z') + return "/"; + *s = i++; + } + return as; +} + +void +regerror(char *s) +{ + USED(s); + error(Q); +} |