#include "em.h" main(argc, argv) char **argv; { register char *p1, *p2; #ifdef ERRORS register eflag; #endif ERRORS extern int onintr(); extern int terminate(); #ifdef AUTOW extern int catchclock(); signal(SIGCLOK, catchclock); #endif AUTOW onquit = signal(SIGQUIT, 1); signal(SIGTERM, terminate); onhup = signal(SIGHUP, 0); if ((*argv)[1] == 'm') vflag = 1; elfic = 0; argv++; if (argc > 1 && **argv=='-') { p1 = &(*argv)[1]; while (*p1 != '\0') switch (*p1++) { case 'e': elfic = 1; break; case 'l': lflag++; break; #ifndef ERRORS case 's': vflag = -1; #else case 's': sflag++; #endif ERRORS break; } if ((*argv)[1] == '\0') vflag = -1; argv++; argc--; } if (argc>1) { p1 = *argv; p2 = savedfile; while (*p2++ = *p1++); breaks(p1 - 3); globp = "r"; } fendcore = sbrk(0); if (vflag > 0) putnls("Editor"); #ifdef ERRORS istty = (gtty(0, linebuf) != -1); /* flogs linebuf */ eflag = 0; setexit(); /* catch init errors */ if (eflag) exit(1); eflag = 1; #endif ERRORS margin = LBSIZE - 40; #ifdef N_LINES lines = LINES; #endif #ifdef ERRORS linenr = 1; #endif firstime = 1; tfile = -1; init(); if ((signal(SIGINTR, 1) & 01) == 0) signal(SIGINTR, onintr); setexit(); commands(vflag); unlink(tfname); exit(0); } terminate() { signal(SIGTERM, 1); if (dol != zero) writeout("saved.file"); putnls("System going down - tmp file written to \"saved.file\""); unlink(tfname); exit(1); } #ifdef AUTOW catchclock() { register int ad1, ad2, oldintr; long csav; char bell BELL; if (delaywrite) { writewaiting++; return; } signal(SIGCLOK, catchclock); justwrit++; if (dol != zero) /* empty file */ { oldintr = signal(SIGINTR, 1); ad1 = addr1; ad2 = addr2; addr2 = 0; csav = count; write(2, &bell, 1); writeout(-3); write(2, &bell, 1); addr1 = ad1; addr2 = ad2; count = csav; signal(SIGINTR, oldintr); } clktim(writetime); } #endif AUTOW commands(prompt) { int getfile(), gettty(); register *a1, c; register char *p; int r, n; int fd; for (;;) { #ifdef ERRORS if (prompt != -2) currlnnr = linenr; /* i.e., not global */ #endif ERRORS if (pflag) { pflag = 0; addr1 = addr2 = dot; goto print; } if (prompt>0 && globp==0) putch(PROMPT); addr1 = addr2 = 0; xflag = 0; #ifdef AUTOW if (writewaiting) { delaywriting = writewaiting = 0; catchclock(); justwrit = 0; } #endif AUTOW #ifndef ADDRESS do { addr1 = addr2; if ((a1 = address())==0) { c = getchar(); break; } addr2 = a1; if ((c=getchar()) == ';') { c = ','; dot = a1; } } while (c==','); #else a1 = address(); if ((c = getchar()) == ';' && a1) { dot = addr1 = addr2 = a1; a1 = address(); c = getchar(); } if (c == ',') { if (a1 == 0) if (dol == zero) error(30); else addr1 = zero + 1; else addr1 = a1; if ((a1 = address()) == 0) addr2 = dol; else addr2 = a1; c = getchar(); } else addr2 = a1; #endif ADDRESS if (addr1==0) addr1 = addr2; if (c>='A' && c<='Z') c =| 040; switch(c) { case 'a': setdot(); newline(); append(gettty, addr2); continue; case 'b': c = peekc = getchar(); if (c=='+' || c=='-') peekc = 0; else if (c != '\n') error(20); newline(); margin = c == '-' ? LBSIZE - 40 : LENGTH - 20; continue; #ifndef CHDIR case 'c': setdot(); #else case 'c': if (addr2 == 0 && (peekc = getchar()) == 'd') { peekc = 0; if (getchar() != ' ') error(20); do c = getchar(); while (c == ' '); if (c == '\n') error(20); p = linebuf; do *p++ = c; while ((c = getchar()) != '\n'); *p = '\0'; if (chdir(linebuf)) error(8); continue; } setdot(); #endif CHDIR newline(); fd = *addr1; /* borrow 'fd' */ delete(); if (append(gettty, addr1-1) > 0) retag(*addr1, fd); continue; case 'd': setdot(); newline(); delete(); continue; case 'e': if (elfic) error(22); setnoaddr(); if ((peekc = getchar()) != ' ') error(20); savedfile[0] = 0; init(); addr2 = zero; goto caseread; #ifndef MISC case 'f': if (elfic) error(22); setnoaddr(); #else case 'f': setnoaddr(); #endif if ((c = getchar()) != '\n') { peekc = c; #ifdef MISC if (elfic && *savedfile) error(22); #endif #ifndef SEARCH_STRING savedfile[0] = 0; #endif SEARCH_STRING filename(1); } putnls(savedfile); continue; case 'g': global(1); continue; case 'h': newline(); if ((fd = open("/usr/lib/emhelp", 0)) < 0) { putnls("/usr/lib/emhelp not found"); continue; } while ((n = read(fd, linebuf, 512)) > 0) write(1, linebuf, n); close(fd); continue; case 'i': setdot(); nonzero(); newline(); append(gettty, addr2-1); continue; #ifdef JOIN case 'j': if (addr2 == 0) addr2 = (addr1 = dot) + 1; if (addr1 > addr2) error(23); if (addr1 == addr2) addr2++; nonzero(); nocmpress = 1; if ((peekc = getchar()) == 'c') { nocmpress--; peekc = 0; } newline(); join(); continue; #endif JOIN case 'k': if ((c = getchar()) < 'a' || c > 'z') error(24); newline(); setdot(); nonzero(); names[c-'a'] = *addr2 | 01; continue; case 'm': move(0); continue; case '\n': if (addr2==0) addr2 = dot+1; addr1 = addr2; if (lflag) listf++; goto print; case 'l': listf++; case 'p': newline(); print: setdot(); nonzero(); a1 = addr1; do putnls(getline(*a1++)); while (a1 <= addr2); dot = addr2; listf = 0; continue; case 'o': setdot(); #ifdef AUTOW delaywrite++; #endif AUTOW op(globp); #ifdef AUTOW delaywrite = 0; #endif AUTOW continue; case 'q': setnoaddr(); newline(); #ifndef MISC if (elfic) { firstime = 1; writeout(0); } #else if (elfic && dol != zero) writeout(0); #endif unlink(tfname); exit(0); case 'r': caseread: filename(0); #ifdef AUTOW delaywrite++; #endif AUTOW if ((io = open(file, 0)) < 0) { lastc = '\n'; error(0); } setall(); ninbuf = 0; append(getfile, addr2); exfile(); #ifdef NULLS if (listf && vflag >= 0) /* borrows 'listf' */ { putchar('('); if ((count = listf) > 0) putd(); else puts("many"); putnls(" null(s) stripped from file)"); } listf = 0; #endif NULLS #ifdef AUTOW delaywrite = 0; #endif AUTOW continue; case 'x': xflag = 1; case 's': setdot(); nonzero(); substitute(globp); xflag = 0; continue; #ifndef AUTOW case 't': #else case 't': if ((peekc = getchar()) == 'i') /* timeout */ { fd = 0; peekc = 0; if (*savedfile == 0) error(25); while (((c = getchar()) >= '0') && c <= '9') fd = fd * 10 + c - '0'; if (c != '\n') error(20); writetime = fd * 60; clktim(writetime); continue; } #endif AUTOW move(1); continue; case 'v': global(0); continue; case 'w': if (elfic) error(22); #ifdef AUTOW delaywrite++; #endif AUTOW #ifndef DRM writeout(0); #else if ((peekc = getchar()) == 'a') { peekc = 0; writeout(-1); } #ifdef MISC else if (peekc == 'x') { peekc = 0; writeout(-2); } #endif MISC else writeout(0); #endif DRM #ifdef AUTOW delaywrite = 0; #endif AUTOW continue; #ifdef PRINT_STRING case 'z': setnoaddr(); newline(); printstrings(); continue; #endif PRINT_STRING case '"': setdot(); #ifdef N_LINES fetchnr(); #endif N_LINES newline(); if (addr1 < zero) error(23); dot = addr1; if (dot == dol) error(23); addr1 = dot + 1; #ifndef N_LINES addr2 = dot + LINES - 1; #else addr2 = dot + lines - 1; #endif N_LINES if (addr2 > dol) addr2 = dol; outlines: pflag = listf; for (a1 = addr1; a1 <= addr2; a1++) putnls(getline(*a1)); dot = addr2; pflag = listf = 0; continue; case '&': setdot(); #ifdef N_LINES fetchnr(); #endif N_LINES newline(); nonzero(); dot = addr1; #ifndef N_LINES addr1 = dot - (LINES-2); #else addr1 = dot - (lines-2); #endif N_LINES addr2 = dot; if (addr1 <= zero) addr1 = zero + 1; goto outlines; case '%': #ifdef N_LINES fetchnr(); #endif N_LINES newline(); pflag = listf; listf = 0; setdot(); nonzero(); dot = addr1; #ifndef N_LINES addr1 = dot - (LINES/2 - 2); addr2 = dot + (LINES/2 - 2); #else addr1 = dot - (lines/2 - 2); addr2 = dot + (lines/2 - 2); #endif N_LINES if (addr1 <= zero) addr1 = zero + 1; if (addr2 > dol) addr2 = dol; listf = pflag; for (a1 = addr1; a1 <= addr2; a1++) { if (a1 == dot) screensplit(); putnls(getline(*a1)); if (a1 == dot) screensplit(); } pflag = listf = 0; continue; case '>': if (vflag > 0) vflag = 0; newline(); reset(); case '<': vflag = 1; newline(); reset(); case '=': setall(); newline(); count = (addr2-zero) & 077777; putd(); putchar('\n'); continue; case '!': setnoaddr(); unix(); continue; #ifndef ERRORS case EOF: if (prompt == -2 || ttyn(0) == 'x') return; #else case EOF: if (prompt == -2 || ! istty) return; #endif ERRORS continue; } error(20); } } writeout(filen) char *filen; { register char *p1, *p2; #ifdef MISC extern write(); #endif #ifdef DRM register flag 0; #ifndef MISC if (filen == -1) { flag++; filen = 0; } #else if (filen == -1 || filen == -2) { flag = filen; filen = 0; } #endif MISC #endif DRM setall(); nonzero(); if (filen == 0) { if (elfic) { p1 = savedfile; if (*p1 == 0) error(25); p2 = file; while (*p2++ = *p1++); } else filename(0); filen = file; } #ifndef DRM if ((io = creat(filen, 0600)) < 0) error(1); #else if (flag == -1 && (io = open(filen, 1)) >= 0) seek(io, 0, 2); #ifndef MISC else if ((io = creat(filen, 0600)) < 0) error(1); #else #ifdef AUTOW else if (filen == -3) { if ((io = creat(savedfile, 0600)) < 0) { putnls("Auto-write - cannot write file ?"); return; } } #endif else if ((io = creat(filen, flag == -2 ? 0700 : 0600)) < 0) error(1); #endif MISC #endif DRM #ifdef MISC if (iblock >= 0 && ichanged) { blkio(iblock, ibuff, write); ichanged = 0; } if (oblock >= 0) blkio(oblock, obuff, write); #endif putfile(); exfile(); } address() { register *a1, minus, c; int n; int relerr; minus = 0; a1 = 0; for (;;) { c = getchar(); if ('0'<=c && c<='9') { n = 0; do { n =* 10; n =+ c - '0'; } while ((c = getchar())>='0' && c<='9'); peekc = c; if (a1==0) a1 = zero; if (minus<0) n = -n; a1 =+ n; minus = 0; continue; } relerr = 0; if (a1 || minus) relerr++; switch(c) { case ' ': case '\t': continue; case '+': minus++; if (a1==0) a1 = dot; continue; case '-': case '^': minus--; if (a1==0) a1 = dot; continue; case '?': case '/': compile(c); a1 = dot; for (;;) { if (c=='/') { a1++; if (a1 > dol) a1 = zero; } else if (--a1 < zero) a1 = dol; if (execute(0, a1)) break; if (a1==dot) error(21); } break; case '$': a1 = dol; break; case '.': a1 = dot; break; case '\'': if ((c = getchar()) < 'a' || c > 'z') error(24); c =- 'a'; for (a1 = zero+1; a1 <= dol; a1++) if (names[c] == (*a1|01)) break; break; default: peekc = c; if (a1==0) return(0); a1 =+ minus; if (a1<zero || a1>dol) error(23); return(a1); } if (relerr) error(20); } } setdot() { if (addr2 == 0) addr1 = addr2 = dot; if (addr1 > addr2) error(23); } setall() { if (addr2==0) { addr1 = zero+1; addr2 = dol; if (dol==zero) addr1 = zero; } setdot(); } setnoaddr() { if (addr2) error(20); } nonzero() { if (addr1<=zero || addr2>dol) error(23); } newline() { register c; if ((c = getchar()) == '\n') return; if (c=='p' || c=='l' || c=='P' || c=='L') { pflag++; if (c=='l' || c=='L') listf++; if (getchar() == '\n') return; } error(20); } #ifdef N_LINES fetchnr() { register int n; register char c; if ((c = getchar()) >= '0' && c <= '9') { n = 0; do { n =* 10; n =+ c - '0'; } while ((c = getchar()) >= '0' && c <= '9'); if (n < 4) error(20); /* min. is 4 lines */ lines = n; } peekc = c; } #endif N_LINES retag (newlabel, oldlabel) { register int ol, nl; register int *ip; ol = oldlabel | 01; nl = newlabel | 01; for (ip = &names[0]; ip < &names[26]; ip++) if (*ip == ol) *ip = nl; } filename(flag) { register char *p1, *p2; register c; #ifdef MISC chkflg = 1; #endif MISC count = 0; c = getchar(); if (c=='\n' || c==EOF) { if (elfic && !firstime) error(22); else firstime = 0; p1 = savedfile; if (*p1==0) error(25); p2 = file; while (*p2++ = *p1++); #ifdef MISC chkflg = -1; #endif MISC return; } if (c!=' ') error(20); while ((c = getchar()) == ' '); if (c=='\n') error(20); p1 = file; do *p1++ = c; while ((c = getchar()) != '\n'); *p1++ = 0; #ifndef SEARCH_STRING if (savedfile[0]==0) #else if (flag || savedfile[0]==0) #endif SEARCH_STRING { p1 = savedfile; p2 = file; while (*p1++ = *p2++); breaks(p1 - 3); } } breaks(p) register char *p; { if (*p++ == '.' && (*p == 'r' || *p == 'n')) margin = LENGTH - 20; } exfile() { close(io); io = -1; #ifndef AUTOW if (vflag >= 0) { #else if (vflag>=0 && !justwrit) { #endif AUTOW putd(); putchar('\n'); } } onintr() { signal(SIGINTR, onintr); putchar('\n'); lastc = '\n'; error(26); } error(type) { register c; #ifdef ERRORS register char *sp; static char *sysmsgs[] /* system-type failures */ { "Open", /* type 0 == file non-existant */ "Create", /* type 1 == creat fails */ "Write", /* type 2 == write error */ "Gtty", /* type 3 == gtty failed for std input */ "Fork", /* type 4 == fork failed */ "Temp i/o", /* type 5 == i/o on temp file failed */ "Create temp", /* type 6 == creat temp file failed */ "Open temp", /* type 7 == open temp file failed */ "Chdir", /* type 8 == chdir failed */ }; static char *msgs[] /* editor-type failures */ { "Syntax", /* type 20 == syntax (+ others) */ "No match", /* type 21 == match fail */ "Elfic", /* type 22 == not allowed in elfic */ "Address", /* type 23 == illegal address(s) */ "Reg name", /* type 24 == invalid register name */ "File", /* type 25 == no file specified */ "Interrupt", /* type 26 == interrupted */ "Line size", /* type 27 == line too big */ "Too many lines", /* type 28 == out of core */ "Temp size", /* type 29 == out of temp space */ "Buffer empty", /* type 30 == null file */ "Command too long", /* type 31 == UNIX command too long */ "&, %, or subexpression undefined", /* type 32 == ...in the strings */ }; extern char *sys_errlst[]; extern int sys_nerr; extern int errno; #endif ERRORS listf = count = 0; #ifndef ERRORS if (type==21) putnls("??"); else putnls("?"); seek(0, 0, 2); #else pflag = (type != 0 && type != 21); /* flog 'pflag' as cleared later anyway */ if (! istty) { if (vflag >= 0 || pflag) { count = currlnnr; putd(); putchar(' '); } if (pflag) seek(0,0,2); } if (sflag) { if (type == 21) putnls("??"); else putnls("?"); } else if (vflag >= 0 || pflag) { if (type == 23 && dol==zero) type = 30; if (type < 20) sp = sysmsgs[type]; else sp = msgs[type - 20]; while (*sp) putchar(*sp++); if (type < 20 && errno < sys_nerr) { sp = sys_errlst[errno]; puts(": "); while (*sp) putchar(*sp++); } putnls(" ?"); } #endif ERRORS pflag = 0; if (globp) lastc = '\n'; globp = 0; peekc = lastc; while ((c = getchar()) != '\n' && c != EOF); if (io > 0) { close(io); io = -1; } reset(); } getchar() { #ifdef AUTOW register count; #endif if (lastc=peekc) { peekc = 0; return(lastc); } if (globp) { if ((lastc = *globp++) != 0) return(lastc); globp = 0; return(EOF); } #ifndef AUTOW if (read(0, &lastc, 1) <= 0) return(lastc = EOF); #else while ((count = read(0, &lastc, 1)) <= 0) if (count < 0 && justwrit) justwrit = 0; else if (! istty) return(lastc = EOF); #endif AUTOW lastc =& 0177; #ifdef ERRORS if (! istty && lastc=='\n') linenr++; #endif ERRORS return(lastc); } gettty() { register c, gf; register char *p; p = linebuf; gf = globp; while ((c = getchar()) != '\n') { if (c==EOF) { if (gf) peekc = c; return(c); } if ((c =& 0177) == 0) continue; *p++ = c; if (p >= &linebuf[LBSIZE-2]) error(27); } *p++ = 0; if (linebuf[0]=='.' && linebuf[1]==0) return(EOF); return(0); } #ifdef MISC checkfile(fstwd) register fstwd; { static list[] { 01, /* dec object */ 0404, /* pascal obj */ 0407, 0410, 0411, 0412, /* objects */ 017437, /* packed */ 0177545, 0177555, /* archives */ 0, /* end-of-list */ }; register *lp list; while (*lp) if (*lp++ == fstwd) { putnls("Illegal file type"); return 1; } return 0; } #endif MISC getfile() { register c; register char *lp, *fp; lp = linebuf; fp = nextip; do { if (--ninbuf < 0) { if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0) #ifndef NULLS return(EOF); #else if (lp == linebuf) return(EOF); else { if (vflag >= 0) putnls("No `\\n' on last line - `\\n' added."); if (lp >= &linebuf[LBSIZE]) { lastc = '\n'; error(27); } *lp = 0; return(0); } #endif NULLS fp = genbuf; #ifdef MISC if (chkflg) { if (checkfile(genbuf->integer)) { if (chkflg < 0) savedfile[0] = 0; return EOF; } chkflg = 0; } #endif MISC } if (lp >= &linebuf[LBSIZE]) { lastc = '\n'; error(27); } #ifndef NULLS if ((*lp++ = c = *fp++ & 0177) == 0) { lp--; continue; } #else if ((*lp++ = c = *fp++ & 0177) == 0) { lp--; if (listf >= 0) listf++; continue; } #endif NULLS count++; } while (c != '\n'); *--lp = 0; nextip = fp; return(0); } putfile() { int *a1; register char *fp, *lp; register nib; nib = 512; fp = genbuf; a1 = addr1; do { lp = getline(*a1++); for (;;) { if (--nib < 0) { nib = fp - genbuf; if (write(io, genbuf, nib) != nib) error(2); nib = 511; fp = genbuf; } count++; if ((*fp++ = *lp++) == 0) { fp[-1] = '\n'; break; } } } while (a1 <= addr2); nib = fp - genbuf; if (write(io, genbuf, nib) != nib) error(2); } append(f, a) int (*f)(); { register *a1, *a2, *rdot; int tl; nline = 0; dot = a; while ((*f)() == 0) { if (dol >= endcore) { if (sbrk(1024) == -1) error(28); endcore.integer =+ 1024; } tl = putline(linebuf); nline++; a1 = ++dol; a2 = a1+1; rdot = ++dot; while (a1 > rdot) *--a2 = *--a1; *rdot = tl; } return(nline); } unix() { #ifndef UNIXCMD register savint, pid, rpid; int retcode; char c, *lp, *fp; char workbuffer[UNIXBUFL]; #else int savint, pid, retcode; register rpid; register char *lp, *fp; #endif pid = 0; #ifndef UNIXCMD c = getchar(); if (c != '!') { lp = unixbuffer; for (;;) { if (c == '\n') if (lp!=unixbuffer && lp[-1]==BACKSL) lp--; else break; *lp++ = c; c = getchar(); } *lp = '\0'; } else { pid = 1; while (getchar() != '\n'); } lp = workbuffer; fp = unixbuffer; while ((c = *fp++) != '\0') { if (c == '%') if (lp!=unixbuffer && lp[-1]==BACKSL) lp--; else { pid = 1; for (rpid = 0; savedfile[rpid] != '\0'; rpid++) *lp++ = savedfile[rpid]; continue; } *lp++ = c; } *lp = '\0'; if (pid) { putchar('!'); putnls(workbuffer); } #else lp = linebuf; for (;;) { if ((*lp = getchar()) == '\n') break; if (*lp == '!') { fp = unixbuffer; while (*lp++ = *fp++) if (lp >= &linebuf[UNIXBUFL]) error(31); lp--; pid++; continue; } if (*lp == BACKSL) if ((fp = getchar()) == '\n' || fp == '!') *lp = fp; else *++lp = fp; if (++lp >= &linebuf[UNIXBUFL]) error(31); } *lp = '\0'; fp = unixbuffer; lp = linebuf; retcode = 0; while (*fp++ = *lp++); fp = unixbuffer; lp = linebuf; while (*lp = *fp++) if (*lp == BACKSL) { if ((*++lp = *fp++) == '%') *--lp = '%'; lp++; } else if (*lp++ == '%') { pid++; lp--; for (rpid = 0; *lp++ = savedfile[rpid]; rpid++) if (lp >= &linebuf[LBSIZE]) error(31); lp--; } if (pid) { putchar('!'); putnls(linebuf); } #endif UNIXCMD #ifdef AUTOW clktim(0); #endif if ((pid = fork()) == 0) { signal(SIGHUP, onhup); signal(SIGQUIT, onquit); #ifndef UNIXCMD execl("/bin/sh", "sh", "-c", workbuffer, 0); #else execl("/bin/sh", "sh", "-c", linebuf, 0); #endif exit(1); } #ifdef ERRORS if (pid == -1) error(4); /* fork failed */ #endif ERRORS savint = signal(SIGINTR, 1); #ifndef AUTOW while ((rpid = wait(&retcode)) != pid && rpid != -1); #else while ((rpid = waitx(&retcode)) != pid); clktim(writetime); #endif AUTOW signal(SIGINTR, savint); putnls("!"); } #ifdef JOIN join() { register char *bp, *lp; register nl; int tl, toggle, *lptr; lp = linebuf; toggle = 1; for (lptr = addr1; lptr <= addr2; lptr++) { tl = *lptr; bp = getblock(tl,READ); nl = nleft; tl =& ~0177; while (*lp = *bp++) { if (toggle || nocmpress) lp++; else if (*lp != ' ' && *lp != CTRLI) { toggle++; lp++; } if (--nl == 0) { bp = getblock(tl=+0200,READ); nl = nleft; } if (lp >= &linebuf[LBSIZE-2]) error(27); } if (lp >= &linebuf[LBSIZE-1]) error(27); while (--lp >= linebuf && (*lp==' ' || *lp==CTRLI) && ! nocmpress); *++lp = ' '; lp++; toggle = 0; } lp[-1] = 0; retag(*addr1 = putline(linebuf), *addr1); addr1++; if (addr2 == dol) delete(); else { delete(); dot--; } } #endif JOIN delete() { register *a1, *a2, *a3; nonzero(); a1 = addr1; a2 = addr2+1; a3 = dol; dol =- a2 - a1; do *a1++ = *a2++; while (a2 <= a3); a1 = addr1; if (a1 > dol) a1 = dol; dot = a1; } getline(tl) { register char *bp, *lp; register nl; lp = linebuf; bp = getblock(tl, READ); nl = nleft; tl =& ~0177; while (*lp++ = *bp++) if (--nl == 0) { bp = getblock(tl=+0200, READ); nl = nleft; } return(linebuf); } putline(buffer) char buffer[]; { register char *bp, *buff; register nl; int tl; buff = buffer; tl = tline; bp = getblock(tl, WRITE); nl = nleft; tl =& ~0177; while (*bp = *buff++) { if (*bp++ == '\n') { *--bp = 0; linebp = buff; break; } if (--nl == 0) { bp = getblock(tl=+0200, WRITE); nl = nleft; } } nl = tline; tline =+ (((buff-buffer)+07)>>2) & 077776; return(nl); } /* format of core words : bbbbbbbbboooooog * where : * b is block nr. in temp. file; * o is (offset in block) / 8; * g is set on global matches */ getblock(atl, iof) { extern read(), write(); register bno, off; bno = (atl>>7)&0777; off = (atl<<2)&0770; if (bno >= 511) error(29); nleft = 512 - off; if (bno==iblock) { ichanged =| iof; return(ibuff+off); } if (bno==oblock) return(obuff+off); if (iof==READ) { if (ichanged) blkio(iblock, ibuff, write); ichanged = 0; iblock = bno; blkio(bno, ibuff, read); return(ibuff+off); } if (oblock>=0) blkio(oblock, obuff, write); oblock = bno; return(obuff+off); } blkio(b, buf, iofcn) int (*iofcn)(); { seek(tfile, b, 3); if ((*iofcn)(tfile, buf, 512) != 512) error(5); } init() { register char *p; register pid; close(tfile); tline = 0; iblock = -1; oblock = -1; tfname = "/tmp/exxxxx"; ichanged = 0; pid = getpid(); for (p = &tfname[11]; p > &tfname[6];) { *--p = (pid&07) + '0'; pid =>> 3; } if ((tfile = creat(tfname, 0600)) < 0) error(6); close(tfile); if ((tfile = open(tfname, 2)) < 0) error(7); #ifndef ERRORS brk(fendcore); endcore = fendcore - 2; #else brk(fendcore+INITLINES); endcore = fendcore - 2 + INITLINES; #endif ERRORS dot = zero = dol = fendcore; } global(k) { register char *gp; register c; register int *a1; char globuf[GBSIZE]; #ifdef ADDRESS int dflt 0; #endif if (globp) error(20); setall(); nonzero(); if ((c=getchar())=='\n') error(20); #ifndef ADDRESS compile(c); #else if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z') { peekc = c; dflt++; } else compile(c); #endif ADDRESS gp = globuf; while ((c = getchar()) != '\n') { if (c==EOF) error(20); if (c==BACKSL) { c = getchar(); if (c!='\n') *gp++ = BACKSL; } *gp++ = c; if (gp >= &globuf[GBSIZE-2]) error(27); } *gp++ = '\n'; *gp++ = 0; #ifdef GLOBAL c = 0; #endif GLOBAL for (a1=zero; a1<=dol; a1++) { *a1 =& ~01; #ifndef ADDRESS if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k) #else if (a1>=addr1 && a1<=addr2 && (dflt || execute(0, a1))==k) #endif ADDRESS #ifndef GLOBAL *a1 =| 01; #else { *a1 =| 01; c++; } #endif GLOBAL } #ifdef GLOBAL if (c == 0) error(21); #endif GLOBAL for (a1=zero; a1<=dol; a1++) { if (*a1 & 01) { *a1 =& ~01; dot = a1; globp = globuf; commands(-2); a1 = zero; } } } substitute(inglob) { #ifdef BETTER_SWAP register char *sp, *lp; #endif BETTER_SWAP register *a1; int gsubf; int nn; int nflag; int getsub(); gsubf = compsub(); nflag = gsubf > 1; nn = 0; gsubf =& 01; gsubf =| xflag; for (a1 = addr1; a1 <= addr2; a1++) { if (execute(0, a1)==0) continue; inglob =| 01; #ifdef BETTER_SWAP ssp = genbuf; slp = linebuf; #endif BETTER_SWAP if (confirmed()) { dosub(); nn++; } else donothing(); if (gsubf) { while (*loc2) { if (execute(1)==0) break; if (confirmed()) { dosub(); nn++; } else donothing(); } } #ifdef BETTER_SWAP sp = ssp; lp = slp; while (*sp++ = *lp++) if (sp >= &genbuf[LBSIZE]) error(27); retag(*a1 = putline(genbuf), *a1); #else retag(*a1 = putline(linebuf), *a1); #endif BETTER_SWAP append(getsub, a1); a1 =+ nline; addr2 =+ nline; } if (inglob==0) error(21); if (nflag) { putchar(' '); count = nn; putd(); putchar('\n'); } }