aboutsummaryrefslogtreecommitdiff
path: root/user/bin/ed.c
diff options
context:
space:
mode:
authornthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
committernthnluu <nate1299@me.com>2024-01-28 21:20:27 -0500
commitc63f340d90800895f007de64b7d2d14624263331 (patch)
tree2c0849fa597dd6da831c8707b6f2603403778d7b /user/bin/ed.c
Created student weenix repository
Diffstat (limited to 'user/bin/ed.c')
-rw-r--r--user/bin/ed.c1757
1 files changed, 1757 insertions, 0 deletions
diff --git a/user/bin/ed.c b/user/bin/ed.c
new file mode 100644
index 0000000..5510876
--- /dev/null
+++ b/user/bin/ed.c
@@ -0,0 +1,1757 @@
+/*
+ * ed is the standard text editor.
+ *
+ * I think that Keith was the one who ported ed to weenix. Thanks Keith.
+ * Note: dap also helped in 2007, but it still doesn't work.
+ * Working version added in 2010.
+ */
+
+/* Just for fun:
+ * From: patl@athena.mit.edu (Patrick J. LoPresti)
+ * Subject: The True Path (long)
+ * Date: 11 Jul 91 03:17:31 GMT
+ * Newsgroups: alt.religion.emacs,alt.slack
+ *
+ * When I log into my Xenix system with my 110 baud teletype, both vi
+ * *and* Emacs are just too damn slow. They print useless messages like,
+ * 'C-h for help' and '"foo" File is read only'. So I use the editor
+ * that doesn't waste my VALUABLE time.
+ *
+ * Ed, man! !man ed
+ *
+ * ED(1) UNIX Programmer's Manual ED(1)
+ *
+ * NAME
+ * ed - text editor
+ *
+ * SYNOPSIS
+ * ed [ - ] [ -x ] [ name ]
+ * DESCRIPTION
+ * Ed is the standard text editor.
+ * ---
+ *
+ * Computer Scientists love ed, not just because it comes first
+ * alphabetically, but because it's the standard. Everyone else loves ed
+ * because it's ED!
+ *
+ * "Ed is the standard text editor."
+ *
+ * And ed doesn't waste space on my Timex Sinclair. Just look:
+ *
+ * -rwxr-xr-x 1 root 24 Oct 29 1929 /bin/ed
+ * -rwxr-xr-t 4 root 1310720 Jan 1 1970 /usr/ucb/vi
+ * -rwxr-xr-x 1 root 5.89824e37 Oct 22 1990 /usr/bin/emacs
+ *
+ * Of course, on the system *I* administrate, vi is symlinked to ed.
+ * Emacs has been replaced by a shell script which 1) Generates a syslog
+ * message at level LOG_EMERG; 2) reduces the user's disk quota by 100K;
+ * and 3) RUNS ED!!!!!!
+ *
+ * "Ed is the standard text editor."
+ *
+ * Let's look at a typical novice's session with the mighty ed:
+ *
+ * golem> ed
+ *
+ * ?
+ * help
+ * ?
+ * ?
+ * ?
+ * quit
+ * ?
+ * exit
+ * ?
+ * bye
+ * ?
+ * hello?
+ * ?
+ * eat flaming death
+ * ?
+ * ^C
+ * ?
+ * ^C
+ * ?
+ * ^D
+ * ?
+ *
+ * ---
+ * Note the consistent user interface and error reportage. Ed is
+ * generous enough to flag errors, yet prudent enough not to overwhelm
+ * the novice with verbosity.
+ *
+ * "Ed is the standard text editor."
+ *
+ * Ed, the greatest WYGIWYG editor of all.
+ *
+ * ED IS THE TRUE PATH TO NIRVANA! ED HAS BEEN THE CHOICE OF EDUCATED
+ * AND IGNORANT ALIKE FOR CENTURIES! ED WILL NOT CORRUPT YOUR PRECIOUS
+ * BODILY FLUIDS!! ED IS THE STANDARD TEXT EDITOR! ED MAKES THE SUN
+ * SHINE AND THE BIRDS SING AND THE GRASS GREEN!!
+ *
+ * When I use an editor, I don't want eight extra KILOBYTES of worthless
+ * help screens and cursor positioning code! I just want an EDitor!!
+ * Not a "viitor". Not a "emacsitor". Those aren't even WORDS!!!! ED!
+ * ED! ED IS THE STANDARD!!!
+ *
+ * TEXT EDITOR.
+ *
+ * When IBM, in its ever-present omnipotence, needed to base their
+ * "edlin" on a UNIX standard, did they mimic vi? No. Emacs? Surely
+ * you jest. They chose the most karmic editor of all. The standard.
+ *
+ * Ed is for those who can *remember* what they are working on. If you
+ * are an idiot, you should use Emacs. If you are an Emacs, you should
+ * not be vi. If you use ED, you are on THE PATH TO REDEMPTION. THE
+ * SO-CALLED "VISUAL" EDITORS HAVE BEEN PLACED HERE BY ED TO TEMPT THE
+ * FAITHLESS. DO NOT GIVE IN!!! THE MIGHTY ED HAS SPOKEN!!!
+ *
+ * ?
+ *
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * Editor
+ */
+
+#define SIGHUP 1
+#define SIGINTR 2
+#define SIGQUIT 3
+#define FNSIZE 64
+#define LBSIZE 512
+#define ESIZE 128
+#define GBSIZE 256
+#define NBRA 5
+
+#define CBRA 1
+#define CCHR 2
+#define CDOT 4
+#define CCL 6
+#define NCCL 8
+#define CDOL 10
+#define CEOF 11
+#define CKET 12
+
+#define STAR 01
+
+#define error errfunc()
+#define READ 0
+#define WRITE 1
+
+char peekc;
+char lastc;
+char savedfile[FNSIZE];
+char file[FNSIZE];
+char linebuf[LBSIZE];
+char rhsbuf[LBSIZE / 2];
+char expbuf[ESIZE + 4];
+int circfl;
+int *zero;
+int *dot;
+int *dol;
+int *endcore;
+int *fendcore;
+int *addr1;
+int *addr2;
+char genbuf[LBSIZE];
+int count[2];
+char *nextip;
+char *linebp;
+int ninbuf;
+int io;
+int pflag;
+int onhup;
+int onquit;
+int vflag = 1;
+int listf;
+int col;
+char *globp;
+int tfile = -1;
+int tline;
+char tfname[] = "/tmp/exxxxx";
+char *loc1;
+char *loc2;
+char *locs;
+char ibuff[512];
+int iblock = -1;
+char obuff[512];
+int oblock = -1;
+int ichanged;
+int nleft;
+
+void errfunc();
+
+/* int *errlab=(int*)errfunc; */
+char TMPERR[] = "TMP";
+int names[26];
+char *braslist[NBRA];
+char *braelist[NBRA];
+
+void init();
+
+void commands();
+
+int *address();
+
+void setdot();
+
+void newline();
+
+int append(int (*f)(), int *a);
+
+void delete ();
+
+void setnoaddr();
+
+void filename();
+
+int gettty();
+
+void global(int k);
+
+void nonzero();
+
+void move(int cflag);
+
+char *getline(int tl);
+
+void setall();
+
+void exfile();
+
+void substitute(long inglob);
+
+void putfile();
+
+void putd();
+
+void dounix();
+
+void compile(int c);
+
+int execute(int gf, int *addr);
+
+int putline();
+
+char *getblock(int atl, int iof);
+
+int getchar();
+
+void blkio(int b, char *buf, void *);
+
+int compsub();
+
+void dosub();
+
+char *place(char *asp, char *al1, char *al2);
+
+void reverse(int *aa1, int *aa2);
+
+int advance(char *alp, char *aep);
+
+int cclass(char *aset, int ac, int af);
+
+void puts(char *as);
+
+void putchar(char ac);
+
+void reset();
+
+void setexit();
+
+extern int strlen(const char *s);
+
+int creat(const char *fname, mode_t mode) { return open(fname, O_CREAT, mode); }
+
+int signal(int a1, ...) { return 0; }
+
+int main(int argc, char **argv)
+{
+ register char *p1, *p2;
+
+ onquit = signal(SIGQUIT, 1);
+ onhup = signal(SIGHUP, 1);
+ argv++;
+ if (argc > 1 && **argv == '-')
+ {
+ vflag = 0;
+ /* allow debugging quits? */
+ if ((*argv)[1] == 'q')
+ {
+ signal(SIGQUIT, 0);
+ vflag++;
+ }
+ argv++;
+ argc--;
+ }
+ if (argc > 1)
+ {
+ p1 = *argv;
+ p2 = savedfile;
+ while ((*p2++ = *p1++))
+ ;
+ globp = "r";
+ }
+ fendcore = sbrk(0);
+ init();
+ /* setexit(); */
+ commands();
+ unlink(tfname);
+ return 0;
+}
+
+int getfile();
+
+void commands()
+{
+ register int *a1, c;
+
+ for (;;)
+ {
+ if (pflag)
+ {
+ pflag = 0;
+ addr1 = addr2 = dot;
+ goto print;
+ }
+ addr1 = 0;
+ addr2 = 0;
+ do
+ {
+ addr1 = addr2;
+ if ((a1 = address()) == 0)
+ {
+ c = getchar();
+ break;
+ }
+ addr2 = a1;
+ if ((c = getchar()) == ';')
+ {
+ c = ',';
+ dot = a1;
+ }
+ } while (c == ',');
+ if (addr1 == 0)
+ {
+ addr1 = addr2;
+ }
+ switch (c)
+ {
+ case 'a':
+ setdot();
+ newline();
+ append(gettty, addr2);
+ continue;
+
+ case 'c':
+ delete ();
+ append(gettty, addr1 - 1);
+ continue;
+
+ case 'd':
+ delete ();
+ continue;
+
+ case 'e':
+ setnoaddr();
+ if ((peekc = getchar()) != ' ')
+ error;
+ savedfile[0] = 0;
+ init();
+ addr2 = zero;
+ goto caseread;
+
+ case 'f':
+ setnoaddr();
+ if ((c = getchar()) != '\n')
+ {
+ peekc = c;
+ savedfile[0] = 0;
+ filename();
+ }
+ puts(savedfile);
+ continue;
+
+ case 'g':
+ global(1);
+ continue;
+
+ case 'i':
+ setdot();
+ nonzero();
+ newline();
+ append(gettty, addr2 - 1);
+ continue;
+
+ case 'k':
+ if ((c = getchar()) < 'a' || c > 'z')
+ error;
+ newline();
+ setdot();
+ nonzero();
+ names[c - 'a'] = *addr2 | 01;
+ continue;
+
+ case 'm':
+ move(0);
+ continue;
+
+ case '\n':
+ if (addr2 == 0)
+ {
+ addr2 = dot + 1;
+ }
+ addr1 = addr2;
+ goto print;
+
+ case 'l':
+ listf++;
+ newline();
+ goto print;
+ case 'p':
+ newline();
+ print:
+ setdot();
+ nonzero();
+ a1 = addr1;
+ do
+ puts(getline(*a1++));
+ while (a1 <= addr2);
+ dot = addr2;
+ listf = 0;
+ continue;
+
+ case 'q':
+ setnoaddr();
+ newline();
+ unlink(tfname);
+ exit(0);
+
+ case 'r':
+ caseread:
+ filename();
+ if ((io = open(file, O_RDONLY, 0)) < 0)
+ {
+ lastc = '\n';
+ error;
+ }
+ setall();
+ ninbuf = 0;
+ append(getfile, addr2);
+ exfile();
+ continue;
+
+ case 's':
+ setdot();
+ nonzero();
+ substitute((long)globp);
+ continue;
+
+ case 't':
+ move(1);
+ continue;
+
+ case 'v':
+ global(0);
+ continue;
+
+ case 'w':
+ setall();
+ nonzero();
+ filename();
+ if ((io = open(file, O_CREAT | O_RDWR | O_TRUNC, 0666)) < 0)
+ error;
+ putfile();
+ exfile();
+ continue;
+
+ case '=':
+ setall();
+ newline();
+ count[1] = (addr2 - zero) & 077777;
+ putd();
+ putchar('\n');
+ continue;
+
+ case '!':
+ dounix();
+ continue;
+
+ case EOF:
+ return;
+ }
+ error;
+ }
+}
+
+int *address()
+{
+ register int *a1, minus, c;
+ int n, 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
+ {
+ a1--;
+ if (a1 < zero)
+ {
+ a1 = dol;
+ }
+ }
+ if (execute(0, a1))
+ {
+ break;
+ }
+ if (a1 == dot)
+ error;
+ }
+ break;
+
+ case '$':
+ a1 = dol;
+ break;
+
+ case '.':
+ a1 = dot;
+ break;
+
+ case '\'':
+ if ((c = getchar()) < 'a' || c > 'z')
+ error;
+ for (a1 = zero; a1 <= dol; a1++)
+ {
+ if (names[c - 'a'] == (*a1 | 01))
+ {
+ break;
+ }
+ }
+ break;
+
+ default:
+ peekc = c;
+ if (a1 == 0)
+ {
+ return (0);
+ }
+ a1 += minus;
+ if (a1 < zero || a1 > dol)
+ error;
+ return (a1);
+ }
+ if (relerr)
+ error;
+ }
+}
+
+void setdot()
+{
+ if (addr2 == 0)
+ {
+ addr1 = addr2 = dot;
+ }
+ if (addr1 > addr2)
+ error;
+}
+
+void setall()
+{
+ if (addr2 == 0)
+ {
+ addr1 = zero + 1;
+ addr2 = dol;
+ if (dol == zero)
+ {
+ addr1 = zero;
+ }
+ }
+ setdot();
+}
+
+void setnoaddr()
+{
+ if (addr2)
+ error;
+}
+
+void nonzero()
+{
+ if (addr1 <= zero || addr2 > dol)
+ error;
+}
+
+void newline()
+{
+ register int c;
+
+ if ((c = getchar()) == '\n')
+ {
+ return;
+ }
+ if (c == 'p' || c == 'l')
+ {
+ pflag++;
+ if (c == 'l')
+ {
+ listf++;
+ }
+ if (getchar() == '\n')
+ {
+ return;
+ }
+ }
+ error;
+}
+
+void filename()
+{
+ register char *p1, *p2;
+ register int c;
+
+ count[1] = 0;
+ c = getchar();
+ if (c == '\n' || c == EOF)
+ {
+ p1 = savedfile;
+ if (*p1 == 0)
+ error;
+ p2 = file;
+ while ((*p2++ = *p1++))
+ ;
+ return;
+ }
+ if (c != ' ')
+ error;
+ while ((c = getchar()) == ' ')
+ ;
+ if (c == '\n')
+ error;
+ p1 = file;
+ do
+ {
+ *p1++ = c;
+ } while ((c = getchar()) != '\n');
+ *p1++ = 0;
+ if (savedfile[0] == 0)
+ {
+ p1 = savedfile;
+ p2 = file;
+ while ((*p1++ = *p2++))
+ ;
+ }
+}
+
+void exfile()
+{
+ close(io);
+ io = -1;
+ if (vflag)
+ {
+ putd();
+ putchar('\n');
+ }
+}
+
+void errfunc(void)
+{
+ register int c;
+
+ listf = 0;
+ puts("?");
+ count[0] = 0;
+ lseek(0, 0, 2);
+ pflag = 0;
+ if (globp)
+ {
+ lastc = '\n';
+ }
+ globp = 0;
+ peekc = lastc;
+ while ((c = getchar()) != '\n' && c != EOF)
+ ;
+ if (io > 0)
+ {
+ close(io);
+ io = -1;
+ }
+ /* reset(); */
+}
+
+int getchar()
+{
+ if ((lastc = peekc))
+ {
+ peekc = 0;
+ return (lastc);
+ }
+ if (globp)
+ {
+ if ((lastc = *globp++) != 0)
+ {
+ return (lastc);
+ }
+ globp = 0;
+ return (EOF);
+ }
+ if (read(0, &lastc, 1) <= 0)
+ {
+ return (lastc = EOF);
+ }
+ lastc &= 0177;
+ return (lastc);
+}
+
+int gettty()
+{
+ register long c, gf;
+ register char *p;
+
+ p = linebuf;
+ gf = (long)globp;
+ while ((c = getchar()) != '\n')
+ {
+ if (c == EOF)
+ {
+ if (gf)
+ {
+ peekc = c;
+ }
+ return (int)(c);
+ }
+ if ((c &= 0177) == 0)
+ {
+ continue;
+ }
+ *p++ = c;
+ if (p >= &linebuf[LBSIZE - 2])
+ error;
+ }
+ *p++ = 0;
+ if (linebuf[0] == '.' && linebuf[1] == 0)
+ {
+ return (EOF);
+ }
+ return (0);
+}
+
+int getfile()
+{
+ register int c;
+ register char *lp, *fp;
+
+ lp = linebuf;
+ fp = nextip;
+ do
+ {
+ if (--ninbuf < 0)
+ {
+ if ((ninbuf = read(io, genbuf, LBSIZE) - 1) < 0)
+ {
+ return (EOF);
+ }
+ fp = genbuf;
+ }
+ if (lp >= &linebuf[LBSIZE])
+ error;
+ if ((*lp++ = c = *fp++ & 0177) == 0)
+ {
+ lp--;
+ continue;
+ }
+ if (++count[1] == 0)
+ {
+ ++count[0];
+ }
+ } while (c != '\n');
+ *--lp = 0;
+ nextip = fp;
+ return (0);
+}
+
+void putfile()
+{
+ int *a1;
+ register char *fp, *lp;
+ register int nib;
+
+ nib = 512;
+ fp = genbuf;
+ a1 = addr1;
+ do
+ {
+ lp = getline(*a1++);
+ for (;;)
+ {
+ if (--nib < 0)
+ {
+ write(io, genbuf, fp - genbuf);
+ nib = 511;
+ fp = genbuf;
+ }
+ if (++count[1] == 0)
+ {
+ ++count[0];
+ }
+ if ((*fp++ = *lp++) == 0)
+ {
+ fp[-1] = '\n';
+ break;
+ }
+ }
+ } while (a1 <= addr2);
+ write(io, genbuf, fp - genbuf);
+}
+
+int append(f, a) int (*f)();
+int *a;
+{
+ register int *a1, *a2, *rdot;
+ int nline, tl;
+ int *corep = (int *)endcore;
+ struct core
+ {
+ int integer;
+ };
+
+ nline = 0;
+ dot = a;
+ while ((*f)() == 0)
+ {
+ if (dol >= endcore)
+ {
+ if (sbrk(1024) == (char *)-1)
+ error;
+ *corep += 1024;
+ }
+ tl = putline();
+ nline++;
+ a1 = ++dol;
+ a2 = a1 + 1;
+ rdot = ++dot;
+ while (a1 > rdot)
+ *--a2 = *--a1;
+ *rdot = tl;
+ }
+ return (nline);
+}
+
+void dounix()
+{
+ register int savint, pid, rpid;
+ int retcode;
+
+ setnoaddr();
+ if ((pid = fork()) == 0)
+ {
+ char *argv[] = {"/bin/sh", 0};
+ char *envp[] = {"PATH=/bin", 0};
+
+ signal(SIGHUP, onhup);
+ signal(SIGQUIT, onquit);
+ execve("/bin/sh", argv, envp);
+ exit(-1);
+ }
+ savint = signal(SIGINTR, 1);
+ while ((rpid = wait(&retcode)) != pid && rpid != -1)
+ ;
+ signal(SIGINTR, savint);
+ puts("!");
+}
+
+void delete ()
+{
+ register int *a1, *a2, *a3;
+
+ setdot();
+ newline();
+ 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;
+}
+
+char *getline(int tl)
+{
+ register char *bp, *lp;
+ register int nl;
+
+ lp = linebuf;
+ bp = getblock(tl, READ);
+ nl = nleft;
+ tl &= ~0377;
+ while ((*lp++ = *bp++))
+ if (--nl == 0)
+ {
+ bp = getblock(tl += 0400, READ);
+ nl = nleft;
+ }
+ return (linebuf);
+}
+
+int putline()
+{
+ register char *bp, *lp;
+ register int nl;
+ int tl;
+
+ lp = linebuf;
+ tl = tline;
+ bp = getblock(tl, WRITE);
+ nl = nleft;
+ tl &= ~0377;
+ while ((*bp = *lp++))
+ {
+ if (*bp++ == '\n')
+ {
+ *--bp = 0;
+ linebp = lp;
+ break;
+ }
+ if (--nl == 0)
+ {
+ bp = getblock(tl += 0400, WRITE);
+ nl = nleft;
+ }
+ }
+ nl = tline;
+ tline += (((lp - linebuf) + 03) >> 1) & 077776;
+ return (nl);
+}
+
+char *getblock(int atl, int iof)
+{
+ register int bno, off;
+
+ bno = (atl >> 8) & 0377;
+ off = (atl << 1) & 0774;
+ if (bno >= 255)
+ {
+ puts(TMPERR);
+ error;
+ }
+ 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, (void *)write);
+ }
+ ichanged = 0;
+ iblock = bno;
+ blkio(bno, ibuff, (void *)read);
+ return (ibuff + off);
+ }
+ if (oblock >= 0)
+ {
+ blkio(oblock, obuff, (void *)write);
+ }
+ oblock = bno;
+ return (obuff + off);
+}
+
+void blkio(int b, char *buf, void *iofcn)
+{
+ int (*iof)(int f, char *b, int len) =
+ (int (*)(int f, char *b, int len))iofcn;
+ lseek(tfile, b, SEEK_SET);
+ if ((*iof)(tfile, buf, 512) != 512)
+ {
+ puts(TMPERR);
+ error;
+ }
+}
+
+void init()
+{
+ register char *p;
+ register int pid;
+
+ close(tfile);
+ tline = 0;
+ iblock = -1;
+ oblock = -1;
+ ichanged = 0;
+ pid = getpid();
+ for (p = &tfname[11]; p > &tfname[6];)
+ {
+ *--p = (pid & 07) + '0';
+ pid >>= 3;
+ }
+ close(creat(tfname, 0600));
+ tfile = open(tfname, O_RDWR, 0);
+ brk(fendcore);
+ dot = zero = dol = fendcore;
+ endcore = fendcore - 2;
+}
+
+void global(int k)
+{
+ register char *gp;
+ register int c;
+ register int *a1;
+ char globuf[GBSIZE];
+
+ if (globp)
+ error;
+ setall();
+ nonzero();
+ if ((c = getchar()) == '\n')
+ error;
+ compile(c);
+ gp = globuf;
+ while ((c = getchar()) != '\n')
+ {
+ if (c == EOF)
+ error;
+ if (c == '\\')
+ {
+ c = getchar();
+ if (c != '\n')
+ {
+ *gp++ = '\\';
+ }
+ }
+ *gp++ = c;
+ if (gp >= &globuf[GBSIZE - 2])
+ error;
+ }
+ *gp++ = '\n';
+ *gp++ = 0;
+ for (a1 = zero; a1 <= dol; a1++)
+ {
+ *a1 &= ~01;
+ if (a1 >= addr1 && a1 <= addr2 && execute(0, a1) == k)
+ {
+ *a1 |= 01;
+ }
+ }
+ for (a1 = zero; a1 <= dol; a1++)
+ {
+ if (*a1 & 01)
+ {
+ *a1 &= ~01;
+ dot = a1;
+ globp = globuf;
+ commands();
+ a1 = zero;
+ }
+ }
+}
+
+int getsub();
+
+void substitute(long inglob)
+{
+ register int gsubf, *a1, nl;
+
+ gsubf = compsub();
+ for (a1 = addr1; a1 <= addr2; a1++)
+ {
+ if (execute(0, a1) == 0)
+ {
+ continue;
+ }
+ inglob |= 01;
+ dosub();
+ if (gsubf)
+ {
+ while (*loc2)
+ {
+ if (execute(1, 0) == 0)
+ {
+ break;
+ }
+ dosub();
+ }
+ }
+ *a1 = putline();
+ nl = append(getsub, a1);
+ a1 += nl;
+ addr2 += nl;
+ }
+ if (inglob == 0)
+ error;
+}
+
+int compsub()
+{
+ register int seof, c;
+ register char *p;
+
+ if ((seof = getchar()) == '\n')
+ error;
+ compile(seof);
+ p = rhsbuf;
+ for (;;)
+ {
+ c = getchar();
+ if (c == '\\')
+ {
+ c = getchar() | 0200;
+ }
+ if (c == '\n')
+ error;
+ if (c == seof)
+ {
+ break;
+ }
+ *p++ = c;
+ if (p >= &rhsbuf[LBSIZE / 2])
+ error;
+ }
+ *p++ = 0;
+ if ((peekc = getchar()) == 'g')
+ {
+ peekc = 0;
+ newline();
+ return (1);
+ }
+ newline();
+ return (0);
+}
+
+int getsub()
+{
+ register char *p1, *p2;
+
+ p1 = linebuf;
+ if ((p2 = linebp) == 0)
+ {
+ return (EOF);
+ }
+ while ((*p1++ = *p2++))
+ ;
+ linebp = 0;
+ return (0);
+}
+
+void dosub()
+{
+ register char *lp, *sp, *rp;
+ int c;
+
+ lp = linebuf;
+ sp = genbuf;
+ rp = rhsbuf;
+ while (lp < loc1)
+ *sp++ = *lp++;
+ while ((c = *rp++))
+ {
+ if (c == '&')
+ {
+ sp = place(sp, loc1, loc2);
+ continue;
+ }
+ else if (c < 0 && (c &= 0177) >= '1' && c < NBRA + '1')
+ {
+ sp = place(sp, braslist[c - '1'], braelist[c - '1']);
+ continue;
+ }
+ *sp++ = c & 0177;
+ if (sp >= &genbuf[LBSIZE])
+ error;
+ }
+ lp = loc2;
+ loc2 = sp + (long)linebuf - (long)genbuf;
+ while ((*sp++ = *lp++))
+ if (sp >= &genbuf[LBSIZE])
+ error;
+ lp = linebuf;
+ sp = genbuf;
+ while ((*lp++ = *sp++))
+ ;
+}
+
+char *place(char *asp, char *al1, char *al2)
+{
+ register char *sp, *l1, *l2;
+
+ sp = asp;
+ l1 = al1;
+ l2 = al2;
+ while (l1 < l2)
+ {
+ *sp++ = *l1++;
+ if (sp >= &genbuf[LBSIZE])
+ error;
+ }
+ return (sp);
+}
+
+int getcopy();
+
+void move(int cflag)
+{
+ register int *adt, *ad1, *ad2;
+
+ setdot();
+ nonzero();
+ if ((adt = address()) == 0)
+ error;
+ newline();
+ ad1 = addr1;
+ ad2 = addr2;
+ if (cflag)
+ {
+ ad1 = dol;
+ append(getcopy, ad1++);
+ ad2 = dol;
+ }
+ 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;
+}
+
+void reverse(int *aa1, int *aa2)
+{
+ register int *a1, *a2, t;
+
+ a1 = aa1;
+ a2 = aa2;
+ for (;;)
+ {
+ t = *--a2;
+ if (a2 <= a1)
+ {
+ return;
+ }
+ *a2 = *a1;
+ *a1++ = t;
+ }
+}
+
+int getcopy()
+{
+ if (addr1 > addr2)
+ {
+ return (EOF);
+ }
+ getline(*addr1++);
+ return (0);
+}
+
+void compile(int aeof)
+{
+ register int eof, c;
+ register char *ep;
+ char *lastep;
+ char bracket[NBRA], *bracketp;
+ int nbra;
+ int cclcnt;
+
+ ep = expbuf;
+ eof = aeof;
+ bracketp = bracket;
+ nbra = 0;
+ if ((c = getchar()) == eof)
+ {
+ if (*ep == 0)
+ error;
+ return;
+ }
+ circfl = 0;
+ if (c == '^')
+ {
+ c = getchar();
+ circfl++;
+ }
+ if (c == '*')
+ {
+ goto cerror;
+ }
+ peekc = c;
+ for (;;)
+ {
+ if (ep >= &expbuf[ESIZE])
+ {
+ goto cerror;
+ }
+ c = getchar();
+ if (c == eof)
+ {
+ *ep++ = CEOF;
+ return;
+ }
+ if (c != '*')
+ {
+ lastep = ep;
+ }
+ switch (c)
+ {
+ case '\\':
+ if ((c = getchar()) == '(')
+ {
+ if (nbra >= NBRA)
+ {
+ goto cerror;
+ }
+ *bracketp++ = nbra;
+ *ep++ = CBRA;
+ *ep++ = nbra++;
+ continue;
+ }
+ if (c == ')')
+ {
+ if (bracketp <= bracket)
+ {
+ goto cerror;
+ }
+ *ep++ = CKET;
+ *ep++ = *--bracketp;
+ continue;
+ }
+ *ep++ = CCHR;
+ if (c == '\n')
+ {
+ goto cerror;
+ }
+ *ep++ = c;
+ continue;
+
+ case '.':
+ *ep++ = CDOT;
+ continue;
+
+ case '\n':
+ goto cerror;
+
+ case '*':
+ if (*lastep == CBRA || *lastep == CKET)
+ error;
+ *lastep |= STAR;
+ continue;
+
+ case '$':
+ if ((peekc = getchar()) != eof)
+ {
+ goto defchar;
+ }
+ *ep++ = CDOL;
+ continue;
+
+ case '[':
+ *ep++ = CCL;
+ *ep++ = 0;
+ cclcnt = 1;
+ if ((c = getchar()) == '^')
+ {
+ c = getchar();
+ ep[-2] = NCCL;
+ }
+ do
+ {
+ if (c == '\n')
+ {
+ goto cerror;
+ }
+ *ep++ = c;
+ cclcnt++;
+ if (ep >= &expbuf[ESIZE])
+ {
+ goto cerror;
+ }
+ } while ((c = getchar()) != ']');
+ lastep[1] = cclcnt;
+ continue;
+
+ defchar:
+ default:
+ *ep++ = CCHR;
+ *ep++ = c;
+ }
+ }
+cerror:
+ expbuf[0] = 0;
+ error;
+}
+
+int execute(gf, addr) int gf;
+int *addr;
+{
+ register char *p1, *p2, c;
+
+ if (gf)
+ {
+ if (circfl)
+ {
+ return (0);
+ }
+ p1 = linebuf;
+ p2 = genbuf;
+ while ((*p1++ = *p2++))
+ ;
+ locs = p1 = loc2;
+ }
+ else
+ {
+ if (addr == zero)
+ {
+ return (0);
+ }
+ p1 = getline(*addr);
+ locs = 0;
+ }
+ p2 = expbuf;
+ if (circfl)
+ {
+ loc1 = p1;
+ return (advance(p1, p2));
+ }
+ /* fast check for first character */
+ if (*p2 == CCHR)
+ {
+ c = p2[1];
+ do
+ {
+ if (*p1 != c)
+ {
+ continue;
+ }
+ if (advance(p1, p2))
+ {
+ loc1 = p1;
+ return (1);
+ }
+ } while (*p1++);
+ return (0);
+ }
+ /* regular algorithm */
+ do
+ {
+ if (advance(p1, p2))
+ {
+ loc1 = p1;
+ return (1);
+ }
+ } while (*p1++);
+ return (0);
+}
+
+int advance(char *alp, char *aep)
+{
+ register char *lp, *ep, *curlp;
+
+ lp = alp;
+ ep = aep;
+ for (;;)
+ {
+ switch (*ep++)
+ {
+ case CCHR:
+ if (*ep++ == *lp++)
+ {
+ continue;
+ }
+ return (0);
+
+ case CDOT:
+ if (*lp++)
+ {
+ continue;
+ }
+ return (0);
+
+ case CDOL:
+ if (*lp == 0)
+ {
+ continue;
+ }
+ return (0);
+
+ case CEOF:
+ loc2 = lp;
+ return (1);
+
+ case CCL:
+ if (cclass(ep, *lp++, 1))
+ {
+ ep += *ep;
+ continue;
+ }
+ return (0);
+
+ case NCCL:
+ if (cclass(ep, *lp++, 0))
+ {
+ ep += *ep;
+ continue;
+ }
+ return (0);
+
+ case CBRA:
+ braslist[(int)*ep++] = lp;
+ continue;
+
+ case CKET:
+ braelist[(int)*ep++] = lp;
+ continue;
+
+ case CDOT | STAR:
+ curlp = lp;
+ while (*lp++)
+ ;
+ goto star;
+
+ case CCHR | STAR:
+ curlp = lp;
+ while (*lp++ == *ep)
+ ;
+ ep++;
+ goto star;
+
+ case CCL | STAR:
+ case NCCL | STAR:
+ curlp = lp;
+ while (cclass(ep, *lp++, ep[-1] == (CCL | STAR)))
+ ;
+ ep += *ep;
+ goto star;
+
+ star:
+ do
+ {
+ lp--;
+ if (lp == locs)
+ {
+ break;
+ }
+ if (advance(lp, ep))
+ {
+ return (1);
+ }
+ } while (lp > curlp);
+ return (0);
+
+ default:
+ error;
+ }
+ }
+}
+
+int cclass(char *aset, int ac, int af)
+{
+ register char *set, c;
+ register int n;
+
+ set = aset;
+ if ((c = ac) == 0)
+ {
+ return (0);
+ }
+ n = *set++;
+ while (--n)
+ if (*set++ == c)
+ {
+ return (af);
+ }
+ return (!af);
+}
+
+void putd()
+{
+#if 0
+ register r;
+ extern ldivr;
+
+ count[1] = ldiv(count[0], count[1], 10);
+ count[0] = 0;
+ r = ldivr;
+ if (count[1])
+ putd();
+ putchar(r + '0');
+#else
+ printf("%d", count[1]);
+#endif
+}
+
+void puts(char *as)
+{
+ register char *sp;
+
+ sp = as;
+ col = 0;
+ while (*sp)
+ putchar(*sp++);
+ putchar('\n');
+}
+
+char line[80];
+char *linp = line;
+
+void putchar(char ac)
+{
+ register char *lp;
+ register int c;
+
+ lp = linp;
+ c = ac;
+ if (listf)
+ {
+ col++;
+ if (col >= 72)
+ {
+ col = 0;
+ *lp++ = '\\';
+ *lp++ = '\n';
+ }
+ if (c == '\t')
+ {
+ c = '>';
+ goto esc;
+ }
+ if (c == '\b')
+ {
+ c = '<';
+ esc:
+ *lp++ = '-';
+ *lp++ = '\b';
+ *lp++ = c;
+ goto out;
+ }
+ if (c < ' ' && c != '\n')
+ {
+ *lp++ = '\\';
+ *lp++ = (c >> 3) + '0';
+ *lp++ = (c & 07) + '0';
+ col += 2;
+ goto out;
+ }
+ }
+ *lp++ = c;
+out:
+ if (c == '\n' || lp >= &line[64])
+ {
+ linp = line;
+ write(1, line, lp - line);
+ return;
+ }
+ linp = lp;
+}
+
+/*
+ * Get process ID routine if system call is unavailable.
+
+getpid()
+{
+ register f;
+ int b[1];
+
+ f = open("/dev/kmem", 0);
+ if(f < 0)
+ return(-1);
+ seek(f, 0140074, 0);
+ read(f, b, 2);
+ seek(f, b[0]+8, 0);
+ read(f, b, 2);
+ close(f);
+ return(b[0]);
+}
+ */