--- /dev/null
+[COPYRIGHT file: V7/x86 distribution]
+
+
+The following copyright notice applies to the UNIX Version 7 and
+32V UNIX portions of this distribution:
+
+Copyright (C) Caldera International Inc. 2001-2002. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+Redistributions of source code and documentation must retain the
+above copyright notice, this list of conditions and the following
+disclaimer. Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+
+All advertising materials mentioning features or use of this software
+must display the following acknowledgement:
+
+This product includes software developed or owned by Caldera
+International, Inc.
+
+Neither the name of Caldera International, Inc. nor the names of
+other contributors may be used to endorse or promote products derived
+from this software without specific prior written permission.
+
+USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENCE BY CALDERA
+INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+The following copyright notice applies to the Amsterdam Compiler
+Kit portions of this distribution:
+
+Copyright (c) 1987,1990, 1993 Vrije Universiteit, Amsterdam, The Netherlands.
+All rights reserved.
+
+Redistribution and use of the Amsterdam Compiler Kit in source and
+binary forms, with or without modification, are permitted provided
+that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of Vrije Universiteit nor the names of the
+ software authors or contributors may be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
+CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL VRIJE UNIVERSITEIT OR ANY AUTHORS OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+The following copyright notice applies to the Berkeley Software
+Distribution portions of this distribution:
+
+Copyright (c) 1979, 1980 The Regents of the University of California.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+This product includes software developed by the University of
+California, Berkeley and its contributors.
+4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+
+Modifications, enhancements, and additions to the supplied software
+are by Robert Nordier, and the following copyright notice applies to
+such modifications, enhancements, and additions, and to the overall
+V7/x86 distribution:
+
+Copyright (c) 1999-2007 Robert Nordier. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied and defloated for FUZIX */
+
+/*
+ * acct [ -w wtmp ] [ -d ] [ -p ] [ people ]
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <time.h>
+#include <utmp.h>
+#include <sys/types.h>
+
+#define TSIZE 33
+#define USIZE 200
+struct utmp ibuf;
+
+struct ubuf {
+ char uname[8];
+ long utime;
+} ubuf[USIZE];
+
+struct tbuf {
+ struct ubuf *userp;
+ long ttime;
+} tbuf[TSIZE];
+
+const char *wtmp;
+int pflag, byday;
+long dtime;
+time_t midnight;
+long lastime;
+int pcount;
+char **pptr;
+
+const long day = 86400L;
+const long dayandahalf = 86400L + 86400L / 2;
+
+
+void update(struct tbuf *tp, int f)
+{
+ int j;
+ struct ubuf *up;
+ long t, t1;
+
+ if (f)
+ t = midnight;
+ else
+ t = ibuf.ut_time;
+ if (tp->userp) {
+ t1 = t - tp->ttime;
+ if (t1 > 0 && t1 < dayandahalf)
+ tp->userp->utime += t1;
+ }
+ tp->ttime = t;
+ if (f)
+ return;
+ if (ibuf.ut_user[0] == '\0') {
+ tp->userp = 0;
+ return;
+ }
+ for (up = ubuf; up < &ubuf[USIZE]; up++) {
+ if (up->uname[0] == '\0')
+ break;
+ for (j = 0; j < 8 && up->uname[j] == ibuf.ut_user[j]; j++);
+ if (j >= 8)
+ break;
+ }
+ for (j = 0; j < 8; j++)
+ up->uname[j] = ibuf.ut_user[j];
+ tp->userp = up;
+}
+
+int among(int i)
+{
+ register int j, k;
+ register char *p;
+
+ if (pcount == 0)
+ return (1);
+ for (j = 0; j < pcount; j++) {
+ p = pptr[j];
+ for (k = 0; k < 8; k++) {
+ if (*p == ubuf[i].uname[k]) {
+ if (*p++ == '\0')
+ return (1);
+ } else
+ break;
+ }
+ }
+ return (0);
+}
+
+void newday(void)
+{
+#if 0
+ time_t ttime;
+ struct timeb tb;
+
+ time(&ttime);
+/* FIXME: do modern style TZ */
+ if (midnight == 0) {
+ midnight = 60 * (long) tb.timezone;
+ if (localtime(&ttime)->tm_isdst)
+ midnight -= 3600;
+ }
+/* END */
+#endif
+ while (midnight <= ibuf.ut_time)
+ midnight += day;
+}
+
+void pdate(void)
+{
+ time_t x;
+
+ if (byday == 0)
+ return;
+ x = midnight - 1;
+ printf("%.6s", ctime(&x) + 4);
+}
+
+void printdeci2(long v, int div)
+{
+ int r = ((int) (v / div)) % 100;
+ if (r)
+ printf(".%02d", r);
+}
+
+void print(void)
+{
+ int i;
+ long ttime, t;
+
+ ttime = 0;
+ for (i = 0; i < USIZE; i++) {
+ if (!among(i))
+ continue;
+ t = ubuf[i].utime;
+ if (t > 0)
+ ttime += t;
+ if (pflag && ubuf[i].utime > 0) {
+ printf("\t%-8.8s%6ld\n",
+ ubuf[i].uname, ubuf[i].utime / 3600L);
+ printdeci2(ubuf[i].utime, 36);
+ }
+ }
+ if (ttime > 0) {
+ pdate();
+ printf("\ttotal%9ld\n", ttime / 3600L);
+ printdeci2(ttime, 36);
+ }
+}
+
+void upall(int f)
+{
+ register struct tbuf *tp;
+
+ for (tp = tbuf; tp < &tbuf[TSIZE]; tp++)
+ update(tp, f);
+}
+
+void loop(void)
+{
+ register int i;
+ register struct tbuf *tp;
+ register struct ubuf *up;
+
+ if (ibuf.ut_line[0] == '|') {
+ dtime = ibuf.ut_time;
+ return;
+ }
+ if (ibuf.ut_line[0] == '}') {
+ if (dtime == 0)
+ return;
+ for (tp = tbuf; tp < &tbuf[TSIZE]; tp++)
+ tp->ttime += ibuf.ut_time - dtime;
+ dtime = 0;
+ return;
+ }
+ if (lastime > ibuf.ut_time || lastime + dayandahalf < ibuf.ut_time)
+ midnight = 0;
+ if (midnight == 0)
+ newday();
+ lastime = ibuf.ut_time;
+ if (byday && ibuf.ut_time > midnight) {
+ upall(1);
+ print();
+ newday();
+ for (up = ubuf; up < &ubuf[USIZE]; up++)
+ up->utime = 0;
+ }
+ if (ibuf.ut_line[0] == '~') {
+ ibuf.ut_user[0] = '\0';
+ upall(0);
+ return;
+ }
+ if (ibuf.ut_line[0] == 't')
+ i = (ibuf.ut_line[3] - '0') * 10 + (ibuf.ut_line[4] - '0');
+ else
+ i = TSIZE - 1;
+ if (i < 0 || i >= TSIZE)
+ i = TSIZE - 1;
+ tp = &tbuf[i];
+ update(tp, 0);
+}
+
+int main(int argc, char *argv[])
+{
+ int c, fl;
+ register int i;
+ FILE *wf;
+
+ wtmp = "/usr/adm/wtmp";
+ while (--argc > 0 && **++argv == '-')
+ switch (*++*argv) {
+ case 'd':
+ byday++;
+ continue;
+
+ case 'w':
+ if (--argc > 0)
+ wtmp = *++argv;
+ continue;
+
+ case 'p':
+ pflag++;
+ continue;
+ }
+ pcount = argc;
+ pptr = argv;
+ if ((wf = fopen(wtmp, "r")) == NULL) {
+ printf("No %s\n", wtmp);
+ exit(1);
+ }
+ for (;;) {
+ if (fread((char *) &ibuf, sizeof(ibuf), 1, wf) != 1)
+ break;
+ fl = 0;
+ for (i = 0; i < 8; i++) {
+ c = ibuf.ut_user[i];
+ if (isdigit(c) || isalpha(c)) {
+ if (fl)
+ goto skip;
+ continue;
+ }
+ if (c == ' ' || c == '\0') {
+ fl++;
+ ibuf.ut_user[i] = '\0';
+ } else
+ goto skip;
+ }
+ loop();
+ skip:;
+ }
+ ibuf.ut_user[0] = '\0';
+ ibuf.ut_line[0] = '~';
+ time(&ibuf.ut_time);
+ loop();
+ print();
+ exit(0);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, const char *argv[])
+{
+ if (argc > 1)
+ acct(argv[1]);
+ else
+ acct((char *)0);
+ if (errno) {
+ perror("accton");
+ exit(1);
+ }
+ exit(0);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+/*
+ * at time mon day
+ * at time wday
+ * at time wday 'week'
+ *
+ */
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define HOUR 100
+#define HALFDAY (12*HOUR)
+#define DAY (24*HOUR)
+#define THISDAY "/usr/spool/at"
+
+const char *days[] = {
+ "sunday",
+ "monday",
+ "tuesday",
+ "wednesday",
+ "thursday",
+ "friday",
+ "saturday",
+};
+
+struct monstr {
+ const char *mname;
+ int mlen;
+} months[] = {
+ {
+ "january", 31}, {
+ "february", 28}, {
+ "march", 31}, {
+ "april", 30}, {
+ "may", 31}, {
+ "june", 30}, {
+ "july", 31}, {
+ "august", 31}, {
+ "september", 30}, {
+ "october", 31}, {
+ "november", 30}, {
+ "december", 31}, {
+0, 0},};
+
+char fname[100];
+int utimev; /* requested time in grains */
+int now; /* when is it */
+int uday; /* day of year to be done */
+int uyear; /* year */
+int today; /* day of year today */
+FILE *file;
+FILE *ifile;
+
+void onintr(int sig)
+{
+ unlink(fname);
+ exit(1);
+}
+
+char *prefix(char *begin, char *full)
+{
+ int c;
+ while (c = *begin++) {
+ if (isupper(c))
+ c = tolower(c);
+ if (*full != c)
+ return (0);
+ else
+ full++;
+ }
+ return (full);
+}
+
+int makeutime(char *pp)
+{
+ register int val;
+ register char *p;
+
+ /* p points to a user time */
+ p = pp;
+ val = 0;
+ while (isdigit(*p)) {
+ val = val * 10 + (*p++ - '0');
+ }
+ if (p - pp < 3)
+ val *= HOUR;
+
+ for (;;) {
+ switch (*p) {
+
+ case ':':
+ ++p;
+ if (isdigit(*p)) {
+ if (isdigit(p[1])) {
+ val += (10 * *p + p[1] - 11 * '0');
+ p += 2;
+ continue;
+ }
+ }
+ fprintf(stderr, "at: bad time format:\n");
+ exit(1);
+
+ case 'A':
+ case 'a':
+ if (val >= HALFDAY + HOUR)
+ val = DAY + 1; /* illegal */
+ if (val >= HALFDAY && val < (HALFDAY + HOUR))
+ val -= HALFDAY;
+ break;
+
+ case 'P':
+ case 'p':
+ if (val >= HALFDAY + HOUR)
+ val = DAY + 1; /* illegal */
+ if (val < HALFDAY)
+ val += HALFDAY;
+ break;
+
+ case 'n':
+ case 'N':
+ val = HALFDAY;
+ break;
+
+ case 'M':
+ case 'm':
+ val = 0;
+ break;
+
+
+ case '\0':
+ case ' ':
+ /* 24 hour time */
+ if (val == DAY)
+ val -= DAY;
+ break;
+
+ default:
+ fprintf(stderr, "at: bad time format\n");
+ exit(1);
+
+ }
+ break;
+ }
+ if (val < 0 || val >= DAY) {
+ fprintf(stderr, "at: time out of range\n");
+ exit(1);
+ }
+ if (val % HOUR >= 60) {
+ fprintf(stderr, "at: illegal minute field\n");
+ exit(1);
+ }
+ utimev = val;
+}
+
+
+int makeuday(int argc, const char *argv[])
+{
+ /* the presumption is that argv[2], argv[3] are either
+ month day OR weekday [week]. Returns either 2 or 3 as last
+ argument used */
+ /* first of all, what's today */
+ time_t tm;
+ int found = -1;
+ char **ps;
+ struct tm *detail;
+ struct monstr *pt;
+
+ time(&tm);
+ detail = localtime(&tm);
+ uday = today = detail->tm_yday;
+ uyear = detail->tm_year;
+ now = detail->tm_hour * 100 + detail->tm_min;
+ if (argc <= 2)
+ return (1);
+ /* is the next argument a month name ? */
+ for (pt = months; pt->mname; pt++) {
+ if (prefix(argv[2], pt->mname)) {
+ if (found < 0)
+ found = pt - months;
+ else {
+ fprintf(stderr, "at: ambiguous month\n");
+ exit(1);
+ }
+ }
+ }
+ if (found >= 0) {
+ if (argc <= 3)
+ return (2);
+ uday = atoi(argv[3]) - 1;
+ if (uday < 0) {
+ fprintf(stderr, "at: illegal day\n");
+ exit(1);
+ }
+ while (--found >= 0)
+ uday += months[found].mlen;
+ if (detail->tm_year % 4 == 0 && uday > 59)
+ uday += 1;
+ return (3);
+ }
+ /* not a month, try day of week */
+ found = -1;
+ for (ps = days; ps < days + 7; ps++) {
+ if (prefix(argv[2], *ps)) {
+ if (found < 0)
+ found = ps - days;
+ else {
+ fprintf(stderr,
+ "at: ambiguous day of week\n");
+ exit(1);
+ }
+ }
+ }
+ if (found < 0)
+ return (1);
+ /* find next day of this sort */
+ uday = found - detail->tm_wday;
+ if (uday <= 0)
+ uday += 7;
+ uday += today;
+ if (argc > 3 && strcmp("week", argv[3]) == 0) {
+ uday += 7;
+ return (3);
+ }
+ return (2);
+}
+
+
+void filename(char *dir, int y, int d, int t)
+{
+ register int i;
+
+ for (i = 0;; i += 53) {
+ sprintf(fname, "%s/%02d.%03d.%04d.%02d", dir, y, d, t,
+ (getpid() + i) % 100);
+ if (access(fname, 0) == -1)
+ return;
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ register int c;
+ char pwbuf[100];
+ FILE *pwfil;
+ int larg;
+
+ /* argv[1] is the user's time: e.g., 3AM */
+ /* argv[2] is a month name or day of week */
+ /* argv[3] is day of month or 'week' */
+ /* another argument might be an input file */
+ if (argc < 2) {
+ fprintf(stderr, "at: arg count\n");
+ exit(1);
+ }
+ makeutime(argv[1]);
+ larg = makeuday(argc, argv) + 1;
+ if (uday == today && larg <= 2 && utimev <= now)
+ uday++;
+ c = uyear % 4 == 0 ? 366 : 365;
+ if (uday >= c) {
+ uday -= c;
+ uyear++;
+ }
+ filename(THISDAY, uyear, uday, utimev);
+ ifile = stdin;
+ if (argc > larg)
+ ifile = fopen(argv[larg], "r");
+ if (ifile == NULL) {
+ fprintf(stderr, "at: cannot open input: %s\n", argv[larg]);
+ exit(1);
+ }
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, onintr);
+ file = fopen(fname, "a");
+ chmod(fname, 0644);
+ if (file == NULL) {
+ fprintf(stderr, "at: cannot open memo file\n");
+ exit(1);
+ }
+ if ((pwfil = popen("pwd", "r")) == NULL) {
+ fprintf(stderr, "at: can't execute pwd\n");
+ exit(1);
+ }
+ fgets(pwbuf, 100, pwfil);
+ pclose(pwfil);
+ fprintf(file, "cd %s", pwbuf);
+ if (environ) {
+ char **ep = environ;
+ while (*ep)
+ fprintf(file, "%s\n", *ep++);
+ }
+ while ((c = getc(ifile)) != EOF) {
+ putc(c, file);
+ }
+ exit(0);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+
+/*
+ * Run programs submitted by at.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+# define ATDIR "/usr/spool/at"
+# define PDIR "past"
+# define LASTF "/usr/spool/at/lasttimedone"
+
+int nowtime;
+int nowdate;
+int nowyear;
+
+void makenowtime(void)
+{
+ time_t t;
+ struct tm *tp;
+
+ time(&t);
+ tp = localtime(&t);
+ nowtime = tp->tm_hour*100 + tp->tm_min;
+ nowdate = tp->tm_yday;
+ nowyear = tp->tm_year;
+}
+
+void updatetime(int t)
+{
+ FILE *tfile;
+
+ tfile = fopen(LASTF, "w");
+ if (tfile == NULL) {
+ fprintf(stderr, "can't write lastfile\n");
+ exit(1);
+ }
+ fprintf(tfile, "%04d\n", t);
+}
+
+void run(char *file)
+{
+ struct stat stbuf;
+ int pid, i;
+ char sbuf[64];
+
+ if (fork()!=0)
+ return;
+ for (i=0; i<15; i++)
+ close(i);
+ dup(dup(open("/dev/null", 0)));
+ /* FIXME: cheaper to do the copy inline */
+ sprintf(sbuf, "/bin/mv %.14s %s", file, PDIR);
+ system(sbuf);
+ chdir(PDIR);
+ if (stat(file, &stbuf) == -1)
+ exit(1);
+ setgid(stbuf.st_gid);
+ setuid(stbuf.st_uid);
+ if (pid = fork()) {
+ if (pid == -1)
+ exit(1);
+ wait((int *)0);
+ unlink(file);
+ exit(0);
+ }
+ nice(3);
+ execl("/bin/sh", "sh", file, 0);
+ execl("/usr/bin/sh", "sh", file, 0);
+ fprintf(stderr, "Can't execl shell\n");
+ exit(1);
+}
+
+#define DIRSIZ 30
+
+int main(int argc, const char *argv[])
+{
+ int tt, day, year, uniq;
+ struct dirent *d;
+ char file[DIRSIZ+1];
+ DIR *dirf;
+
+ if (chdir(ATDIR) < 0) {
+ fprintf(stderr, "Can't chdir\n");
+ exit(1);
+ }
+ makenowtime();
+ if ((dirf = opendir(".")) == NULL) {
+ fprintf(stderr, "Cannot read at directory\n");
+ exit(1);
+ }
+ while (d = readdir(dirf)) {
+ strncpy(file, d->d_name, DIRSIZ);
+ if (sscanf(file, "%2d.%3d.%4d.%2d", &year, &day, &tt, &uniq) != 4)
+ continue;
+ if (nowyear < year)
+ continue;
+ if (nowyear==year && nowdate < day)
+ continue;
+ if (nowyear==year && nowdate==day && nowtime < tt)
+ continue;
+ run(file);
+ }
+ closedir(dirf);
+ updatetime(nowtime);
+ exit(0);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfield for FUZIX */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#define PL 256
+#define ESC '\033'
+#define RLF '\013'
+#define SI '\017'
+#define SO '\016'
+#define GREEK 0200
+#define LINELN 800
+
+char *page[PL];
+char lbuff[LINELN], *line;
+int bflag, xflag, fflag;
+int half;
+int cp, lp;
+int ll, llh, mustwr;
+int pcp = 0;
+char *pgmname;
+
+
+void outc(char c)
+{
+ if (lp > cp) {
+ line = lbuff;
+ lp = 0;
+ }
+
+ while (lp < cp) {
+ switch (*line) {
+ case '\0':
+ *line = ' ';
+ lp++;
+ break;
+
+ case '\b':
+ lp--;
+ break;
+
+ default:
+ lp++;
+ }
+ line++;
+ }
+ while (*line == '\b') {
+ line += 2;
+ }
+ if (bflag || *line == '\0' || *line == ' ')
+ *line = c;
+ else {
+ register char c1, c2, c3;
+ c1 = *++line;
+ *line++ = '\b';
+ c2 = *line;
+ *line++ = c;
+ while (c1) {
+ c3 = *line;
+ *line++ = c1;
+ c1 = c2;
+ c2 = c3;
+ }
+ lp = 0;
+ line = lbuff;
+ }
+}
+
+void store(int lno)
+{
+ lno %= PL;
+ if (page[lno] != 0)
+ free(page[lno]);
+ page[lno] = malloc((unsigned) strlen(lbuff) + 2);
+ if (page[lno] == 0) {
+ fprintf(stderr, "%s: no storage\n", pgmname);
+ exit(2);
+ }
+ strcpy(page[lno], lbuff);
+}
+
+void fetch(int lno)
+{
+ register char *p;
+
+ lno %= PL;
+ p = lbuff;
+ while (*p)
+ *p++ = '\0';
+ line = lbuff;
+ lp = 0;
+ if (page[lno])
+ strcpy(line, page[lno]);
+}
+
+void emit(char *s, int lineno)
+{
+ static int cline = 0;
+ register int ncp;
+ register char *p;
+ static int gflag = 0;
+
+ if (*s) {
+ if (gflag) {
+ putchar(SI);
+ gflag = 0;
+ }
+ while (cline < lineno - 1) {
+ putchar('\n');
+ pcp = 0;
+ cline += 2;
+ }
+ if (cline != lineno) {
+ putchar(ESC);
+ putchar('9');
+ cline++;
+ }
+ if (pcp)
+ putchar('\r');
+ pcp = 0;
+ p = s;
+ while (*p) {
+ ncp = pcp;
+ while (*p++ == ' ') {
+ if ((++ncp & 7) == 0 && !xflag) {
+ pcp = ncp;
+ putchar('\t');
+ }
+ }
+ if (!*--p)
+ break;
+ while (pcp < ncp) {
+ putchar(' ');
+ pcp++;
+ }
+ if (gflag != (*p & GREEK) && *p != '\b') {
+ if (gflag)
+ putchar(SI);
+ else
+ putchar(SO);
+ gflag ^= GREEK;
+ }
+ putchar(*p & ~GREEK);
+ if (*p++ == '\b')
+ pcp--;
+ else
+ pcp++;
+ }
+ }
+}
+
+void incr(void)
+{
+ store(ll++);
+ if (ll > llh)
+ llh = ll;
+ if (ll >= mustwr && page[ll % PL]) {
+ emit(page[ll % PL], ll - PL);
+ mustwr++;
+ free(page[ll % PL]);
+ page[ll % PL] = 0;
+ }
+ fetch(ll);
+}
+
+void decr(void)
+{
+ if (ll > mustwr - PL) {
+ store(ll--);
+ fetch(ll);
+ }
+}
+
+int main(int argc, const char *argv[])
+{
+ int i;
+ int greek;
+ register int c;
+ char fbuff[BUFSIZ];
+
+ setbuf(stdout, fbuff);
+ pgmname = argv[0];
+
+ for (i = 1; i < argc; i++) {
+ register char *p;
+ if (*argv[i] != '-') {
+ fprintf(stderr, "%s: bad option %s\n",
+ pgmname, argv[i]);
+ exit(2);
+ }
+ for (p = argv[i] + 1; *p; p++) {
+ switch (*p) {
+ case 'b':
+ bflag++;
+ break;
+
+ case 'x':
+ xflag++;
+ break;
+
+ case 'f':
+ fflag++;
+ break;
+
+ default:
+ fprintf(stderr,
+ "%s: bad option letter %c\n",
+ pgmname, *p);
+ exit(2);
+ }
+ }
+ }
+
+ for (ll = 0; ll < PL; ll++)
+ page[ll] = 0;
+
+ cp = 0;
+ ll = 0;
+ greek = 0;
+ mustwr = PL;
+ line = lbuff;
+
+ while ((c = getchar()) != EOF) {
+ switch (c) {
+ case '\n':
+ incr();
+ incr();
+ cp = 0;
+ continue;
+
+ case '\0':
+ continue;
+
+ case ESC:
+ c = getchar();
+ switch (c) {
+ case '7': /* reverse full line feed */
+ decr();
+ decr();
+ break;
+
+ case '8': /* reverse half line feed */
+ if (fflag)
+ decr();
+ else {
+ if (--half < -1) {
+ decr();
+ decr();
+ half += 2;
+ }
+ }
+ break;
+
+ case '9': /* forward half line feed */
+ if (fflag)
+ incr();
+ else {
+ if (++half > 0) {
+ incr();
+ incr();
+ half -= 2;
+ }
+ }
+ break;
+ }
+ continue;
+
+ case SO:
+ greek = GREEK;
+ continue;
+
+ case SI:
+ greek = 0;
+ continue;
+
+ case RLF:
+ decr();
+ decr();
+ continue;
+
+ case '\r':
+ cp = 0;
+ continue;
+
+ case '\t':
+ cp = (cp + 8) & -8;
+ continue;
+
+ case '\b':
+ if (cp > 0)
+ cp--;
+ continue;
+
+ case ' ':
+ cp++;
+ continue;
+
+ default:
+ c &= 0177;
+ if (c > 040 && c < 0177) { /* if printable */
+ outc(c | greek);
+ cp++;
+ }
+ continue;
+ }
+ }
+
+ for (i = 0; i < PL; i++)
+ if (page[(mustwr + i) % PL] != 0)
+ emit(page[(mustwr + i) % PL], mustwr + i - PL);
+ emit(" ", (llh + 1) & -2);
+ return 0;
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define LB 256
+int one;
+int two;
+int three;
+
+char ldr[3][3] = { "", "\t", "\t\t" };
+
+FILE *ib1;
+FILE *ib2;
+
+
+FILE *openfil(const char *s)
+{
+ FILE *b;
+ if (s[0] == '-' && s[1] == 0)
+ b = stdin;
+ else if ((b = fopen(s, "r")) == NULL) {
+ fprintf(stderr, "comm: cannot open %s\n", s);
+ exit(1);
+ }
+ return (b);
+}
+
+int rd(FILE * file, char *buf)
+{
+
+ register int i, c;
+ i = 0;
+ while ((c = getc(file)) != EOF) {
+ *buf = c;
+ if (c == '\n' || i > LB - 2) {
+ *buf = '\0';
+ return (0);
+ }
+ i++;
+ buf++;
+ }
+ return (-1);
+}
+
+void wr(char *str, int n)
+{
+
+ switch (n) {
+
+ case 1:
+ if (one)
+ return;
+ break;
+
+ case 2:
+ if (two)
+ return;
+ break;
+
+ case 3:
+ if (three)
+ return;
+ }
+ printf("%s%s\n", ldr[n - 1], str);
+}
+
+void copy(FILE * ibuf, char *lbuf, int n)
+{
+ do {
+ wr(lbuf, n);
+ } while (rd(ibuf, lbuf) >= 0);
+
+ exit(0);
+}
+
+int compare(char *a, char *b)
+{
+ register char *ra, *rb;
+
+ ra = --a;
+ rb = --b;
+ while (*++ra == *++rb)
+ if (*ra == '\0')
+ return (0);
+ if (*ra < *rb)
+ return (1);
+ return (2);
+}
+
+
+int main(int argc, const char *argv[])
+{
+ int l;
+ char lb1[LB], lb2[LB];
+
+ if (argc > 1) {
+ if (*argv[1] == '-' && argv[1][1] != 0) {
+ l = 1;
+ while (*++argv[1]) {
+ switch (*argv[1]) {
+ case '1':
+ if (!one) {
+ one = 1;
+ ldr[1][0] = '\0';
+ ldr[2][l--] = '\0';
+ }
+ break;
+ case '2':
+ if (!two) {
+ two = 1;
+ ldr[2][l--] = '\0';
+ }
+ break;
+ case '3':
+ three = 1;
+ break;
+ default:
+ fprintf(stderr,
+ "comm: illegal flag\n");
+ exit(1);
+ }
+ }
+ argv++;
+ argc--;
+ }
+ }
+
+ if (argc < 3) {
+ fprintf(stderr, "comm: arg count\n");
+ exit(1);
+ }
+
+ ib1 = openfil(argv[1]);
+ ib2 = openfil(argv[2]);
+
+
+ if (rd(ib1, lb1) < 0) {
+ if (rd(ib2, lb2) < 0)
+ exit(0);
+ copy(ib2, lb2, 2);
+ }
+ if (rd(ib2, lb2) < 0)
+ copy(ib1, lb1, 1);
+
+ while (1) {
+
+ switch (compare(lb1, lb2)) {
+
+ case 0:
+ wr(lb1, 3);
+ if (rd(ib1, lb1) < 0) {
+ if (rd(ib2, lb2) < 0)
+ exit(0);
+ copy(ib2, lb2, 2);
+ }
+ if (rd(ib2, lb2) < 0)
+ copy(ib1, lb1, 1);
+ continue;
+
+ case 1:
+ wr(lb1, 1);
+ if (rd(ib1, lb1) < 0)
+ copy(ib2, lb2, 2);
+ continue;
+
+ case 2:
+ wr(lb2, 2);
+ if (rd(ib2, lb2) < 0)
+ copy(ib1, lb1, 1);
+ continue;
+ }
+ }
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+/* FIXME: hardcoded UID 1 assumption */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <signal.h>
+#include <time.h>
+#include <sys/stat.h>
+
+#define LISTS 512
+
+#define EXACT 100
+#define ANY 101
+#define LIST 102
+#define RANGE 103
+#define EOS 104
+
+char crontab[] = "/usr/lib/crontab";
+time_t itime;
+struct tm *loct;
+int flag;
+char *list;
+unsigned listsize;
+
+
+char *cmp(char *p, int v)
+{
+ register char *cp;
+
+ cp = p;
+ switch (*cp++) {
+
+ case EXACT:
+ if (*cp++ != v)
+ flag++;
+ return (cp);
+
+ case ANY:
+ return (cp);
+
+ case LIST:
+ while (*cp != LIST)
+ if (*cp++ == v) {
+ while (*cp++ != LIST);
+ return (cp);
+ }
+ flag++;
+ return (cp + 1);
+
+ case RANGE:
+ if (*cp > v || cp[1] < v)
+ flag++;
+ return (cp + 2);
+ }
+ if (cp[-1] != v)
+ flag++;
+ return (cp);
+}
+
+int number(int c)
+{
+ int n = 0;
+
+ while (isdigit(c)) {
+ n = n * 10 + c - '0';
+ c = getchar();
+ }
+ ungetc(c, stdin);
+ if (n >= 100)
+ return (-1);
+ return (n);
+}
+
+
+void slp(void)
+{
+ int i;
+ time_t t;
+
+ time(&t);
+ i = itime - t;
+ if (i > 0)
+ sleep(i);
+}
+
+void ex(char *s)
+{
+ int st;
+
+ if (fork()) {
+ wait(&st);
+ return;
+ }
+ if (fork())
+ exit(0);
+ freopen("/", "r", stdin);
+ execl("/bin/sh", "sh", "-c", s, 0);
+ exit(0);
+}
+
+void init(void)
+{
+ register i, c;
+ register char *cp;
+ register char *ocp;
+ register int n;
+
+ freopen(crontab, "r", stdin);
+ if (list) {
+ free(list);
+ list = realloc(list, LISTS);
+ } else
+ list = malloc(LISTS);
+ listsize = LISTS;
+ cp = list;
+
+ loop:
+ if (cp > list + listsize - 100) {
+ char *olist;
+ listsize += LISTS;
+ olist = list;
+ free(list);
+ list = realloc(list, listsize);
+ cp = list + (cp - olist);
+ }
+ ocp = cp;
+ for (i = 0;; i++) {
+ do
+ c = getchar();
+ while (c == ' ' || c == '\t');
+ if (c == EOF || c == '\n')
+ goto ignore;
+ if (i == 5)
+ break;
+ if (c == '*') {
+ *cp++ = ANY;
+ continue;
+ }
+ if ((n = number(c)) < 0)
+ goto ignore;
+ c = getchar();
+ if (c == ',')
+ goto mlist;
+ if (c == '-')
+ goto mrange;
+ if (c != '\t' && c != ' ')
+ goto ignore;
+ *cp++ = EXACT;
+ *cp++ = n;
+ continue;
+
+ mlist:
+ *cp++ = LIST;
+ *cp++ = n;
+ do {
+ if ((n = number(getchar())) < 0)
+ goto ignore;
+ *cp++ = n;
+ c = getchar();
+ } while (c == ',');
+ if (c != '\t' && c != ' ')
+ goto ignore;
+ *cp++ = LIST;
+ continue;
+
+ mrange:
+ *cp++ = RANGE;
+ *cp++ = n;
+ if ((n = number(getchar())) < 0)
+ goto ignore;
+ c = getchar();
+ if (c != '\t' && c != ' ')
+ goto ignore;
+ *cp++ = n;
+ }
+ while (c != '\n') {
+ if (c == EOF)
+ goto ignore;
+ if (c == '%')
+ c = '\n';
+ *cp++ = c;
+ c = getchar();
+ }
+ *cp++ = '\n';
+ *cp++ = 0;
+ goto loop;
+
+ ignore:
+ cp = ocp;
+ while (c != '\n') {
+ if (c == EOF) {
+ *cp++ = EOS;
+ *cp++ = EOS;
+ fclose(stdin);
+ return;
+ }
+ c = getchar();
+ }
+ goto loop;
+}
+
+int main(int argc, char *argv[])
+{
+ register char *cp;
+ time_t filetime = 0;
+
+ setuid(1);
+ if (fork())
+ exit(0);
+ chdir("/");
+ freopen(crontab, "r", stdin);
+ freopen("/", "r", stdout);
+ freopen("/", "r", stderr);
+ signal(SIGHUP, SIG_IGN);
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ time(&itime);
+ itime -= localtime(&itime)->tm_sec;
+ fclose(stdin);
+
+ for (;; itime += 60, slp()) {
+ struct stat cstat;
+
+ if (stat(crontab, &cstat) == -1)
+ continue;
+ if (cstat.st_mtime > filetime) {
+ filetime = cstat.st_mtime;
+ init();
+ }
+ loct = localtime(&itime);
+ loct->tm_mon++; /* 1-12 for month */
+ for (cp = list; *cp != EOS;) {
+ flag = 0;
+ cp = cmp(cp, loct->tm_min);
+ cp = cmp(cp, loct->tm_hour);
+ cp = cmp(cp, loct->tm_mday);
+ cp = cmp(cp, loct->tm_mon);
+ cp = cmp(cp, loct->tm_wday);
+ if (flag == 0) {
+ slp();
+ ex(cp);
+ }
+ while (*cp++ != 0);
+ }
+ }
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+/* FIXME: this is *not* strong crypto */
+
+/*
+ * A one-rotor machine designed along the lines of Enigma
+ * but considerably trivialized.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define ROTORSZ 256
+#define MASK 0377
+
+char t1[ROTORSZ];
+char t2[ROTORSZ];
+char t3[ROTORSZ];
+
+void setup(char *pw)
+{
+ int ic, i, k, temp, pf[2];
+ unsigned random;
+ char buf[13];
+ long seed;
+
+ strncpy(buf, pw, 8);
+ while (*pw)
+ *pw++ = '\0';
+ buf[8] = buf[0];
+ buf[9] = buf[1];
+ pipe(pf);
+ if (fork()==0) {
+ close(0);
+ close(1);
+ dup(pf[0]);
+ dup(pf[1]);
+ execl("/usr/lib/makekey", "-", 0);
+ execl("/lib/makekey", "-", 0);
+ exit(1);
+ }
+ write(pf[1], buf, 10);
+ wait((int *)NULL);
+ if (read(pf[0], buf, 13) != 13) {
+ fprintf(stderr, "crypt: cannot generate key\n");
+ exit(1);
+ }
+ seed = 123;
+ for (i=0; i<13; i++)
+ seed = seed*buf[i] + i;
+ for(i=0;i<ROTORSZ;i++)
+ t1[i] = i;
+ for(i=0;i<ROTORSZ;i++) {
+ seed = 5*seed + buf[i%13];
+ random = seed % 65521;
+ k = ROTORSZ-1 - i;
+ ic = (random&MASK)%(k+1);
+ random >>= 8;
+ temp = t1[k];
+ t1[k] = t1[ic];
+ t1[ic] = temp;
+ if(t3[k]!=0) continue;
+ ic = (random&MASK) % k;
+ while(t3[ic]!=0) ic = (ic+1) % k;
+ t3[k] = ic;
+ t3[ic] = k;
+ }
+ for(i=0;i<ROTORSZ;i++)
+ t2[t1[i]&MASK] = i;
+}
+
+int main(int argc, const char *argv[])
+{
+ int i, n1, n2;
+
+ if (argc != 2){
+ setup(getpass("Enter key:"));
+ }
+ else
+ setup(argv[1]);
+ n1 = 0;
+ n2 = 0;
+
+ while((i=getchar()) >=0) {
+ i = t2[(t3[(t1[(i+n1)&MASK]+n2)&MASK]-n2)&MASK]-n1;
+ putchar(i);
+ n1++;
+ if(n1==ROTORSZ) {
+ n1 = 0;
+ n2++;
+ if(n2==ROTORSZ) n2 = 0;
+ }
+ }
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfield for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+
+#define FATAL 0
+#define NFATAL 1
+#define BLK sizeof(struct blk)
+#define PTRSZ sizeof(int *)
+#define HEADSZ 1024
+#define STKSZ 100
+#define RDSKSZ 100
+#define TBLSZ 256
+#define ARRAYST 0241
+#define MAXIND 2048
+#define NL 1
+#define NG 2
+#define NE 3
+#define length(p) ((p)->wt-(p)->beg)
+#define rewind(p) (p)->rd=(p)->beg
+#define create(p) (p)->rd = (p)->wt = (p)->beg
+#define fsfile(p) (p)->rd = (p)->wt
+#define truncate(p) (p)->wt = (p)->rd
+#define sfeof(p) (((p)->rd==(p)->wt)?1:0)
+#define sfbeg(p) (((p)->rd==(p)->beg)?1:0)
+#define sungetc(p,c) *(--(p)->rd)=c
+#define sgetc(p) (((p)->rd==(p)->wt)?EOF:*(p)->rd++)
+#define slookc(p) (((p)->rd==(p)->wt)?EOF:*(p)->rd)
+#define sbackc(p) (((p)->rd==(p)->beg)?EOF:*(--(p)->rd))
+#define sputc(p,c) {if((p)->wt==(p)->last)more(p); *(p)->wt++ = c; }
+#define salterc(p,c) {if((p)->rd==(p)->last)more(p); *(p)->rd++ = c; if((p)->rd>(p)->wt)(p)->wt=(p)->rd;}
+#define sunputc(p) (*( (p)->rd = --(p)->wt))
+#define zero(p) for(pp=(p)->beg;pp<(p)->last;)*pp++='\0'
+#define OUTC(x) {printf("%c",x); if(--count == 0){printf("\\\n"); count=ll;} }
+#define TEST2 {if((count -= 2) <=0){printf("\\\n");count=ll;}}
+#define EMPTY if(stkerr != 0){printf("stack empty\n"); continue; }
+#define EMPTYR(x) if(stkerr!=0){pushp(x);printf("stack empty\n");continue;}
+#define EMPTYS if(stkerr != 0){printf("stack empty\n"); return(1);}
+#define EMPTYSR(x) if(stkerr !=0){printf("stack empty\n");pushp(x);return(1);}
+#define error(p) {printf(p); continue; }
+#define errorrt(p) {printf(p); return(1); }
+
+struct blk {
+ char *rd;
+ char *wt;
+ char *beg;
+ char *last;
+};
+struct sym {
+ struct sym *next;
+ struct blk *val;
+} symlst[TBLSZ];
+struct wblk {
+ struct blk **rdw;
+ struct blk **wtw;
+ struct blk **begw;
+ struct blk **lastw;
+};
+
+struct blk *hfree;
+struct blk *getwd(struct blk *p);
+struct blk *lookwd(struct blk *p);
+struct blk *getdec(struct blk *p, int sc);
+struct blk *morehd(void);
+void release(struct blk *p);
+void putwd(struct blk *p, struct blk *c);
+char *nalloc(char *p, unsigned nbytes);
+void redef(struct blk *p);
+void garbage(char *s);
+void ospace(char *s);
+void more(struct blk *hptr);
+void salterwd(struct wblk *hptr, struct blk *n);
+void seekc(struct blk *hptr, int n);
+void sdump(char *s1, struct blk *hptr);
+struct blk *copy(struct blk *hptr, int size);
+struct blk *salloc(int size);
+int log2(long n);
+void load(void);
+int cond(char c);
+int command(void);
+int subt(void);
+struct blk *scale(struct blk *p, int n);
+struct blk *removc(struct blk *p, int n);
+int eqk(void);
+struct blk *add(struct blk *a1, struct blk *a2);
+void bigot(struct blk *p, int flg);
+void hexot(struct blk *p, int flg);
+void oneot(struct blk *p, int sc, char ch);
+void tenot(struct blk *p, int sc);
+void print(struct blk *hptr);
+void binop(char c);
+void unreadc(char c);
+int readc(void);
+void chsign(struct blk *p);
+struct blk *mult(struct blk *p, struct blk *q);
+struct blk *add0(struct blk *p, int ct);
+struct blk *readin(void);
+struct blk *pop(void);
+void pushp(struct blk *p);
+void onintr(int sig);
+void init(int argc, char *argv[]);
+struct blk *exp(struct blk *base, struct blk *ex);
+struct blk *sqrt(struct blk *p);
+struct blk *removr(struct blk *p, int n);
+int dscale(void);
+struct blk *scalint(struct blk *p);
+struct blk *div(struct blk *ddivd, struct blk *ddivr);
+void commnds(void);
+
+struct blk *arg1, *arg2;
+int svargc;
+char savk;
+char **svargv;
+int dbg;
+int ifile;
+FILE *curfile;
+struct blk *scalptr, *basptr, *tenptr, *inbas;
+struct blk *sqtemp, *chptr, *strptr, *divxyz;
+struct blk *stack[STKSZ];
+struct blk **stkptr, **stkbeg;
+struct blk **stkend;
+int stkerr;
+int lastchar;
+struct blk *readstk[RDSKSZ];
+struct blk **readptr;
+struct blk *rem;
+int k;
+struct blk *irem;
+int skd, skr;
+int neg;
+struct sym *stable[TBLSZ];
+struct sym *sptr, *sfree;
+FILE *fsave;
+long rel;
+long nbytes;
+long all;
+long headmor;
+long obase;
+int fw, fw1, ll;
+void (*outdit) (struct blk *, int);
+int logo;
+int log10;
+int count;
+char *pp;
+char *dummy;
+
+int main(int argc, char *argv[])
+{
+ init(argc, argv);
+ commnds();
+}
+
+void commnds(void)
+{
+ register int c;
+ register struct blk *p, *q;
+ long l;
+ int sign;
+ struct blk **ptr, *s, *t;
+ struct sym *sp;
+ int sk, sk1, sk2;
+ int n, d;
+
+ while (1) {
+ if (((c = readc()) >= '0' && c <= '9')
+ || (c >= 'A' && c <= 'F') || c == '.') {
+ unreadc(c);
+ p = readin();
+ pushp(p);
+ continue;
+ }
+ switch (c) {
+ case ' ':
+ case '\n':
+ case 0377:
+ case EOF:
+ continue;
+ case 'Y':
+ sdump("stk", *stkptr);
+ printf("all %ld rel %ld headmor %ld\n", all, rel,
+ headmor);
+ printf("nbytes %ld\n", nbytes);
+ continue;
+ case '_':
+ p = readin();
+ savk = sunputc(p);
+ chsign(p);
+ sputc(p, savk);
+ pushp(p);
+ continue;
+ case '-':
+ subt();
+ continue;
+ case '+':
+ if (eqk() != 0)
+ continue;
+ binop('+');
+ continue;
+ case '*':
+ arg1 = pop();
+ EMPTY;
+ arg2 = pop();
+ EMPTYR(arg1);
+ sk1 = sunputc(arg1);
+ sk2 = sunputc(arg2);
+ binop('*');
+ p = pop();
+ sunputc(p);
+ savk = sk1 + sk2;
+ if (savk > k && savk > sk1 && savk > sk2) {
+ sk = sk1;
+ if (sk < sk2)
+ sk = sk2;
+ if (sk < k)
+ sk = k;
+ p = removc(p, savk - sk);
+ savk = sk;
+ }
+ sputc(p, savk);
+ pushp(p);
+ continue;
+ case '/':
+ casediv:
+ if (dscale() != 0)
+ continue;
+ binop('/');
+ if (irem != 0)
+ release(irem);
+ release(rem);
+ continue;
+ case '%':
+ if (dscale() != 0)
+ continue;
+ binop('/');
+ p = pop();
+ release(p);
+ if (irem == 0) {
+ sputc(rem, skr + k);
+ pushp(rem);
+ continue;
+ }
+ p = add0(rem, skd - (skr + k));
+ q = add(p, irem);
+ release(p);
+ release(irem);
+ sputc(q, skd);
+ pushp(q);
+ continue;
+ case 'v':
+ p = pop();
+ EMPTY;
+ savk = sunputc(p);
+ if (length(p) == 0) {
+ sputc(p, savk);
+ pushp(p);
+ continue;
+ }
+ if ((c = sbackc(p)) < 0) {
+ error("sqrt of neg number\n");
+ }
+ if (k < savk)
+ n = savk;
+ else {
+ n = k * 2 - savk;
+ savk = k;
+ }
+ arg1 = add0(p, n);
+ arg2 = sqrt(arg1);
+ sputc(arg2, savk);
+ pushp(arg2);
+ continue;
+ case '^':
+ neg = 0;
+ arg1 = pop();
+ EMPTY;
+ if (sunputc(arg1) != 0)
+ error("exp not an integer\n");
+ arg2 = pop();
+ EMPTYR(arg1);
+ if (sfbeg(arg1) == 0 && sbackc(arg1) < 0) {
+ neg++;
+ chsign(arg1);
+ }
+ if (length(arg1) >= 3) {
+ error("exp too big\n");
+ }
+ savk = sunputc(arg2);
+ p = exp(arg2, arg1);
+ release(arg2);
+ rewind(arg1);
+ c = sgetc(arg1);
+ if (sfeof(arg1) == 0)
+ c = sgetc(arg1) * 100 + c;
+ d = c * savk;
+ release(arg1);
+ if (neg == 0) {
+ if (k >= savk)
+ n = k;
+ else
+ n = savk;
+ if (n < d) {
+ q = removc(p, d - n);
+ sputc(q, n);
+ pushp(q);
+ } else {
+ sputc(p, d);
+ pushp(p);
+ }
+ } else {
+ sputc(p, d);
+ pushp(p);
+ }
+ if (neg == 0)
+ continue;
+ p = pop();
+ q = salloc(2);
+ sputc(q, 1);
+ sputc(q, 0);
+ pushp(q);
+ pushp(p);
+ goto casediv;
+ case 'z':
+ p = salloc(2);
+ n = stkptr - stkbeg;
+ if (n >= 100) {
+ sputc(p, n / 100);
+ n %= 100;
+ }
+ sputc(p, n);
+ sputc(p, 0);
+ pushp(p);
+ continue;
+ case 'Z':
+ p = pop();
+ EMPTY;
+ n = (length(p) - 1) << 1;
+ fsfile(p);
+ sbackc(p);
+ if (sfbeg(p) == 0) {
+ if ((c = sbackc(p)) < 0) {
+ n -= 2;
+ if (sfbeg(p) == 1)
+ n += 1;
+ else {
+ if ((c = sbackc(p)) == 0)
+ n += 1;
+ else if (c > 90)
+ n -= 1;
+ }
+ } else if (c < 10)
+ n -= 1;
+ }
+ release(p);
+ q = salloc(1);
+ if (n >= 100) {
+ sputc(q, n % 100);
+ n /= 100;
+ }
+ sputc(q, n);
+ sputc(q, 0);
+ pushp(q);
+ continue;
+ case 'i':
+ p = pop();
+ EMPTY;
+ p = scalint(p);
+ release(inbas);
+ inbas = p;
+ continue;
+ case 'I':
+ p = copy(inbas, length(inbas) + 1);
+ sputc(p, 0);
+ pushp(p);
+ continue;
+ case 'o':
+ p = pop();
+ EMPTY;
+ p = scalint(p);
+ sign = 0;
+ n = length(p);
+ q = copy(p, n);
+ fsfile(q);
+ l = c = sbackc(q);
+ if (n != 1) {
+ if (c < 0) {
+ sign = 1;
+ chsign(q);
+ n = length(q);
+ fsfile(q);
+ l = c = sbackc(q);
+ }
+ if (n != 1) {
+ while (sfbeg(q) == 0)
+ l = l * 100 + sbackc(q);
+ }
+ }
+ logo = log2(l);
+ obase = l;
+ release(basptr);
+ if (sign == 1)
+ obase = -l;
+ basptr = p;
+ outdit = bigot;
+ if (n == 1 && sign == 0) {
+ if (c <= 16) {
+ outdit = hexot;
+ fw = 1;
+ fw1 = 0;
+ ll = 70;
+ release(q);
+ continue;
+ }
+ }
+ n = 0;
+ if (sign == 1)
+ n++;
+ p = salloc(1);
+ sputc(p, -1);
+ t = add(p, q);
+ n += length(t) * 2;
+ fsfile(t);
+ if ((c = sbackc(t)) > 9)
+ n++;
+ release(t);
+ release(q);
+ release(p);
+ fw = n;
+ fw1 = n - 1;
+ ll = 70;
+ if (fw >= ll)
+ continue;
+ ll = (70 / fw) * fw;
+ continue;
+ case 'O':
+ p = copy(basptr, length(basptr) + 1);
+ sputc(p, 0);
+ pushp(p);
+ continue;
+ case '[':
+ n = 0;
+ p = salloc(0);
+ while (1) {
+ if ((c = readc()) == ']') {
+ if (n == 0)
+ break;
+ n--;
+ }
+ sputc(p, c);
+ if (c == '[')
+ n++;
+ }
+ pushp(p);
+ continue;
+ case 'k':
+ p = pop();
+ EMPTY;
+ p = scalint(p);
+ if (length(p) > 1) {
+ error("scale too big\n");
+ }
+ rewind(p);
+ k = sfeof(p) ? 0 : sgetc(p);
+ release(scalptr);
+ scalptr = p;
+ continue;
+ case 'K':
+ p = copy(scalptr, length(scalptr) + 1);
+ sputc(p, 0);
+ pushp(p);
+ continue;
+ case 'X':
+ p = pop();
+ EMPTY;
+ fsfile(p);
+ n = sbackc(p);
+ release(p);
+ p = salloc(2);
+ sputc(p, n);
+ sputc(p, 0);
+ pushp(p);
+ continue;
+ case 'Q':
+ p = pop();
+ EMPTY;
+ if (length(p) > 2) {
+ error("Q?\n");
+ }
+ rewind(p);
+ if ((c = sgetc(p)) < 0) {
+ error("neg Q\n");
+ }
+ release(p);
+ while (c-- > 0) {
+ if (readptr == &readstk[0]) {
+ error("readstk?\n");
+ }
+ if (*readptr != 0)
+ release(*readptr);
+ readptr--;
+ }
+ continue;
+ case 'q':
+ if (readptr <= &readstk[1])
+ exit(0);
+ if (*readptr != 0)
+ release(*readptr);
+ readptr--;
+ if (*readptr != 0)
+ release(*readptr);
+ readptr--;
+ continue;
+ case 'f':
+ if (stkptr == &stack[0])
+ printf("empty stack\n");
+ else {
+ for (ptr = stkptr; ptr > &stack[0];) {
+ print(*ptr--);
+ }
+ }
+ continue;
+ case 'p':
+ if (stkptr == &stack[0])
+ printf("empty stack\n");
+ else {
+ print(*stkptr);
+ }
+ continue;
+ case 'P':
+ p = pop();
+ EMPTY;
+ sputc(p, 0);
+ printf("%s", p->beg);
+ release(p);
+ continue;
+ case 'd':
+ if (stkptr == &stack[0]) {
+ printf("empty stack\n");
+ continue;
+ }
+ q = *stkptr;
+ n = length(q);
+ p = copy(*stkptr, n);
+ pushp(p);
+ continue;
+ case 'c':
+ while (stkerr == 0) {
+ p = pop();
+ if (stkerr == 0)
+ release(p);
+ }
+ continue;
+ case 'S':
+ if (stkptr == &stack[0]) {
+ error("save: args\n");
+ }
+ c = readc() & 0377;
+ sptr = stable[c];
+ sp = stable[c] = sfree;
+ sfree = sfree->next;
+ if (sfree == 0)
+ goto sempty;
+ sp->next = sptr;
+ p = pop();
+ EMPTY;
+ if (c >= ARRAYST) {
+ q = copy(p, PTRSZ);
+ for (n = 0; n < PTRSZ - 1; n++)
+ sputc(q, 0);
+ release(p);
+ p = q;
+ }
+ sp->val = p;
+ continue;
+ sempty:
+ error("symbol table overflow\n");
+ case 's':
+ if (stkptr == &stack[0]) {
+ error("save:args\n");
+ }
+ c = readc() & 0377;
+ sptr = stable[c];
+ if (sptr != 0) {
+ p = sptr->val;
+ if (c >= ARRAYST) {
+ rewind(p);
+ while (sfeof(p) == 0)
+ release(getwd(p));
+ }
+ release(p);
+ } else {
+ sptr = stable[c] = sfree;
+ sfree = sfree->next;
+ if (sfree == 0)
+ goto sempty;
+ sptr->next = 0;
+ }
+ p = pop();
+ sptr->val = p;
+ continue;
+ case 'l':
+ load();
+ continue;
+ case 'L':
+ c = readc() & 0377;
+ sptr = stable[c];
+ if (sptr == 0) {
+ error("L?\n");
+ }
+ stable[c] = sptr->next;
+ sptr->next = sfree;
+ sfree = sptr;
+ p = sptr->val;
+ if (c >= ARRAYST) {
+ rewind(p);
+ while (sfeof(p) == 0) {
+ q = getwd(p);
+ if (q != 0)
+ release(q);
+ }
+ }
+ pushp(p);
+ continue;
+ case ':':
+ p = pop();
+ EMPTY;
+ q = scalint(p);
+ fsfile(q);
+ c = 0;
+ if ((sfbeg(q) == 0) && ((c = sbackc(q)) < 0)) {
+ error("neg index\n");
+ }
+ if (length(q) > 2) {
+ error("index too big\n");
+ }
+ if (sfbeg(q) == 0)
+ c = c * 100 + sbackc(q);
+ if (c >= MAXIND) {
+ error("index too big\n");
+ }
+ release(q);
+ n = readc() & 0377;
+ sptr = stable[n];
+ if (sptr == 0) {
+ sptr = stable[n] = sfree;
+ sfree = sfree->next;
+ if (sfree == 0)
+ goto sempty;
+ sptr->next = 0;
+ p = salloc((c + PTRSZ) * PTRSZ);
+ zero(p);
+ } else {
+ p = sptr->val;
+ if (length(p) - PTRSZ < c * PTRSZ) {
+ q = copy(p, (c + PTRSZ) * PTRSZ);
+ release(p);
+ p = q;
+ }
+ }
+ seekc(p, c * PTRSZ);
+ q = lookwd(p);
+ if (q != NULL)
+ release(q);
+ s = pop();
+ EMPTY;
+ salterwd((struct wblk *) p, s);
+ sptr->val = p;
+ continue;
+ case ';':
+ p = pop();
+ EMPTY;
+ q = scalint(p);
+ fsfile(q);
+ c = 0;
+ if ((sfbeg(q) == 0) && ((c = sbackc(q)) < 0)) {
+ error("neg index\n");
+ }
+ if (length(q) > 2) {
+ error("index too big\n");
+ }
+ if (sfbeg(q) == 0)
+ c = c * 100 + sbackc(q);
+ if (c >= MAXIND) {
+ error("index too big\n");
+ }
+ release(q);
+ n = readc() & 0377;
+ sptr = stable[n];
+ if (sptr != 0) {
+ p = sptr->val;
+ if (length(p) - PTRSZ >= c * PTRSZ) {
+ seekc(p, c * PTRSZ);
+ s = getwd(p);
+ if (s != 0) {
+ q = copy(s, length(s));
+ pushp(q);
+ continue;
+ }
+ }
+ }
+ q = salloc(PTRSZ);
+ putwd(q, (struct blk *) 0);
+ pushp(q);
+ continue;
+ case 'x':
+ execute:
+ p = pop();
+ EMPTY;
+ if ((readptr != &readstk[0]) && (*readptr != 0)) {
+ if ((*readptr)->rd == (*readptr)->wt)
+ release(*readptr);
+ else {
+ if (readptr++ == &readstk[RDSKSZ]) {
+ error("nesting depth\n");
+ }
+ }
+ } else
+ readptr++;
+ *readptr = p;
+ if (p != 0)
+ rewind(p);
+ else {
+ if ((c = readc()) != '\n')
+ unreadc(c);
+ }
+ continue;
+ case '?':
+ if (++readptr == &readstk[RDSKSZ]) {
+ error("nesting depth\n");
+ }
+ *readptr = 0;
+ fsave = curfile;
+ curfile = stdin;
+ while ((c = readc()) == '!')
+ command();
+ p = salloc(0);
+ sputc(p, c);
+ while ((c = readc()) != '\n') {
+ sputc(p, c);
+ if (c == '\\')
+ sputc(p, readc());
+ }
+ curfile = fsave;
+ *readptr = p;
+ continue;
+ case '!':
+ if (command() == 1)
+ goto execute;
+ continue;
+ case '<':
+ case '>':
+ case '=':
+ if (cond(c) == 1)
+ goto execute;
+ continue;
+ default:
+ printf("%o is unimplemented\n", c);
+ }
+ }
+}
+
+struct blk *div(struct blk *ddivd, struct blk *ddivr)
+{
+ int divsign, remsign, offset, divcarry;
+ int carry, dig, magic, d, dd;
+ long c, td, cc;
+ struct blk *ps;
+ register struct blk *p, *divd, *divr;
+
+ rem = 0;
+ p = salloc(0);
+ if (length(ddivr) == 0) {
+ pushp(ddivr);
+ errorrt("divide by 0\n");
+ }
+ divsign = remsign = 0;
+ divr = ddivr;
+ fsfile(divr);
+ if (sbackc(divr) == -1) {
+ divr = copy(ddivr, length(ddivr));
+ chsign(divr);
+ divsign = ~divsign;
+ }
+ divd = copy(ddivd, length(ddivd));
+ fsfile(divd);
+ if (sfbeg(divd) == 0 && sbackc(divd) == -1) {
+ chsign(divd);
+ divsign = ~divsign;
+ remsign = ~remsign;
+ }
+ offset = length(divd) - length(divr);
+ if (offset < 0)
+ goto ddone;
+ seekc(p, offset + 1);
+ sputc(divd, 0);
+ magic = 0;
+ fsfile(divr);
+ c = sbackc(divr);
+ if (c < 10)
+ magic++;
+ c = c * 100 + (sfbeg(divr) ? 0 : sbackc(divr));
+ if (magic > 0) {
+ c = (c * 100 + (sfbeg(divr) ? 0 : sbackc(divr))) * 2;
+ c /= 25;
+ }
+ while (offset >= 0) {
+ fsfile(divd);
+ td = sbackc(divd) * 100;
+ dd = sfbeg(divd) ? 0 : sbackc(divd);
+ td = (td + dd) * 100;
+ dd = sfbeg(divd) ? 0 : sbackc(divd);
+ td = td + dd;
+ cc = c;
+ if (offset == 0)
+ td += 1;
+ else
+ cc += 1;
+ if (magic != 0)
+ td = td << 3;
+ dig = td / cc;
+ rewind(divr);
+ rewind(divxyz);
+ carry = 0;
+ while (sfeof(divr) == 0) {
+ d = sgetc(divr) * dig + carry;
+ carry = d / 100;
+ salterc(divxyz, d % 100);
+ }
+ salterc(divxyz, carry);
+ rewind(divxyz);
+ seekc(divd, offset);
+ carry = 0;
+ while (sfeof(divd) == 0) {
+ d = slookc(divd);
+ d = d - (sfeof(divxyz) ? 0 : sgetc(divxyz)) -
+ carry;
+ carry = 0;
+ if (d < 0) {
+ d += 100;
+ carry = 1;
+ }
+ salterc(divd, d);
+ }
+ divcarry = carry;
+ sbackc(p);
+ salterc(p, dig);
+ sbackc(p);
+ if (--offset >= 0)
+ divd->wt--;
+ }
+ if (divcarry != 0) {
+ salterc(p, dig - 1);
+ salterc(divd, -1);
+ ps = add(divr, divd);
+ release(divd);
+ divd = ps;
+ }
+
+ rewind(p);
+ divcarry = 0;
+ while (sfeof(p) == 0) {
+ d = slookc(p) + divcarry;
+ divcarry = 0;
+ if (d >= 100) {
+ d -= 100;
+ divcarry = 1;
+ }
+ salterc(p, d);
+ }
+ if (divcarry != 0)
+ salterc(p, divcarry);
+ fsfile(p);
+ while (sfbeg(p) == 0) {
+ if (sbackc(p) == 0)
+ truncate(p);
+ else
+ break;
+ }
+ if (divsign < 0)
+ chsign(p);
+ fsfile(divd);
+ while (sfbeg(divd) == 0) {
+ if (sbackc(divd) == 0)
+ truncate(divd);
+ else
+ break;
+ }
+ ddone:
+ if (remsign < 0)
+ chsign(divd);
+ if (divr != ddivr)
+ release(divr);
+ rem = divd;
+ return (p);
+}
+
+int dscale(void)
+{
+ register struct blk *dd, *dr;
+ register struct blk *r;
+ int c;
+
+ dr = pop();
+ EMPTYS;
+ dd = pop();
+ EMPTYSR(dr);
+ fsfile(dd);
+ skd = sunputc(dd);
+ fsfile(dr);
+ skr = sunputc(dr);
+ if (sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)) {
+ sputc(dr, skr);
+ pushp(dr);
+ errorrt("divide by 0\n");
+ }
+ c = k - skd + skr;
+ if (c < 0)
+ r = removr(dd, -c);
+ else {
+ r = add0(dd, c);
+ irem = 0;
+ }
+ arg1 = r;
+ arg2 = dr;
+ savk = k;
+ return (0);
+}
+
+struct blk *removr(struct blk *p, int n)
+{
+ int nn;
+ register struct blk *q, *s, *r;
+
+ rewind(p);
+ nn = (n + 1) / 2;
+ q = salloc(nn);
+ while (n > 1) {
+ sputc(q, sgetc(p));
+ n -= 2;
+ }
+ r = salloc(2);
+ while (sfeof(p) == 0)
+ sputc(r, sgetc(p));
+ release(p);
+ if (n == 1) {
+ s = div(r, tenptr);
+ release(r);
+ rewind(rem);
+ if (sfeof(rem) == 0)
+ sputc(q, sgetc(rem));
+ release(rem);
+ irem = q;
+ return (s);
+ }
+ irem = q;
+ return (r);
+}
+
+struct blk *sqrt(struct blk *p)
+{
+ struct blk *t;
+ struct blk *r, *q, *s;
+ int c, n, nn;
+
+ n = length(p);
+ fsfile(p);
+ c = sbackc(p);
+ if ((n & 1) != 1)
+ c = c * 100 + (sfbeg(p) ? 0 : sbackc(p));
+ n = (n + 1) >> 1;
+ r = salloc(n);
+ zero(r);
+ seekc(r, n);
+ nn = 1;
+ while ((c -= nn) >= 0)
+ nn += 2;
+ c = (nn + 1) >> 1;
+ fsfile(r);
+ sbackc(r);
+ if (c >= 100) {
+ c -= 100;
+ salterc(r, c);
+ sputc(r, 1);
+ } else
+ salterc(r, c);
+ while (1) {
+ q = div(p, r);
+ s = add(q, r);
+ release(q);
+ release(rem);
+ q = div(s, sqtemp);
+ release(s);
+ release(rem);
+ s = copy(r, length(r));
+ chsign(s);
+ t = add(s, q);
+ release(s);
+ fsfile(t);
+ nn = sfbeg(t) ? 0 : sbackc(t);
+ if (nn >= 0)
+ break;
+ release(r);
+ release(t);
+ r = q;
+ }
+ release(t);
+ release(q);
+ release(p);
+ return (r);
+}
+
+struct blk *exp(struct blk *base, struct blk *ex)
+{
+ register struct blk *r, *e, *p;
+ struct blk *e1, *t, *cp;
+ int temp, c, n;
+ r = salloc(1);
+ sputc(r, 1);
+ p = copy(base, length(base));
+ e = copy(ex, length(ex));
+ fsfile(e);
+ if (sfbeg(e) != 0)
+ goto edone;
+ temp = 0;
+ c = sbackc(e);
+ if (c < 0) {
+ temp++;
+ chsign(e);
+ }
+ while (length(e) != 0) {
+ e1 = div(e, sqtemp);
+ release(e);
+ e = e1;
+ n = length(rem);
+ release(rem);
+ if (n != 0) {
+ e1 = mult(p, r);
+ release(r);
+ r = e1;
+ }
+ t = copy(p, length(p));
+ cp = mult(p, t);
+ release(p);
+ release(t);
+ p = cp;
+ }
+ if (temp != 0) {
+ if ((c = length(base)) == 0) {
+ goto edone;
+ }
+ if (c > 1)
+ create(r);
+ else {
+ rewind(base);
+ if ((c = sgetc(base)) <= 1) {
+ create(r);
+ sputc(r, c);
+ } else
+ create(r);
+ }
+ }
+ edone:
+ release(p);
+ release(e);
+ return (r);
+}
+
+void init(int argc, char *argv[])
+{
+ register struct sym *sp;
+
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, onintr);
+ setbuf(stdout, (char *) NULL);
+ svargc = --argc;
+ svargv = argv;
+ while (svargc > 0 && svargv[1][0] == '-') {
+ switch (svargv[1][1]) {
+ default:
+ dbg = 1;
+ }
+ svargc--;
+ svargv++;
+ }
+ ifile = 1;
+ if (svargc <= 0)
+ curfile = stdin;
+ else if ((curfile = fopen(svargv[1], "r")) == NULL) {
+ printf("can't open file %s\n", svargv[1]);
+ exit(1);
+ }
+ dummy = malloc(1);
+ scalptr = salloc(1);
+ sputc(scalptr, 0);
+ basptr = salloc(1);
+ sputc(basptr, 10);
+ obase = 10;
+ log10 = log2(10L);
+ ll = 70;
+ fw = 1;
+ fw1 = 0;
+ tenptr = salloc(1);
+ sputc(tenptr, 10);
+ obase = 10;
+ inbas = salloc(1);
+ sputc(inbas, 10);
+ sqtemp = salloc(1);
+ sputc(sqtemp, 2);
+ chptr = salloc(0);
+ strptr = salloc(0);
+ divxyz = salloc(0);
+ stkbeg = stkptr = &stack[0];
+ stkend = &stack[STKSZ];
+ stkerr = 0;
+ readptr = &readstk[0];
+ k = 0;
+ sp = sptr = &symlst[0];
+ while (sptr < &symlst[TBLSZ]) {
+ sptr->next = ++sp;
+ sptr++;
+ }
+ sptr->next = 0;
+ sfree = &symlst[0];
+ return;
+}
+
+void onintr(int sig)
+{
+
+ signal(SIGINT, onintr);
+ while (readptr != &readstk[0]) {
+ if (*readptr != 0) {
+ release(*readptr);
+ }
+ readptr--;
+ }
+ curfile = stdin;
+ commnds();
+}
+
+void pushp(struct blk *p)
+{
+ if (stkptr == stkend) {
+ printf("out of stack space\n");
+ return;
+ }
+ stkerr = 0;
+ *++stkptr = p;
+ return;
+}
+
+struct blk *pop(void)
+{
+ if (stkptr == stack) {
+ stkerr = 1;
+ return (0);
+ }
+ return (*stkptr--);
+}
+
+struct blk *readin(void)
+{
+ register struct blk *p, *q;
+ int dp, dpct;
+ register int c;
+
+ dp = dpct = 0;
+ p = salloc(0);
+ while (1) {
+ c = readc();
+ switch (c) {
+ case '.':
+ if (dp != 0) {
+ unreadc(c);
+ break;
+ }
+ dp++;
+ continue;
+ case '\\':
+ readc();
+ continue;
+ default:
+ if (c >= 'A' && c <= 'F')
+ c = c - 'A' + 10;
+ else if (c >= '0' && c <= '9')
+ c -= '0';
+ else
+ goto gotnum;
+ if (dp != 0) {
+ if (dpct >= 99)
+ continue;
+ dpct++;
+ }
+ create(chptr);
+ if (c != 0)
+ sputc(chptr, c);
+ q = mult(p, inbas);
+ release(p);
+ p = add(chptr, q);
+ release(q);
+ }
+ }
+ gotnum:
+ unreadc(c);
+ if (dp == 0) {
+ sputc(p, 0);
+ return (p);
+ } else {
+ q = scale(p, dpct);
+ return (q);
+ }
+}
+
+struct blk *add0(struct blk *p, int ct)
+{
+ /* returns pointer to struct with ct 0's & p */
+ register struct blk *q, *t;
+
+ q = salloc(length(p) + (ct + 1) / 2);
+ while (ct > 1) {
+ sputc(q, 0);
+ ct -= 2;
+ }
+ rewind(p);
+ while (sfeof(p) == 0) {
+ sputc(q, sgetc(p));
+ }
+ release(p);
+ if (ct == 1) {
+ t = mult(tenptr, q);
+ release(q);
+ return (t);
+ }
+ return (q);
+}
+
+struct blk *mult(struct blk *p, struct blk *q)
+{
+ register struct blk *mp, *mq, *mr;
+ int sign, offset, carry;
+ int cq, cp, mt, mcr;
+
+ offset = sign = 0;
+ fsfile(p);
+ mp = p;
+ if (sfbeg(p) == 0) {
+ if (sbackc(p) < 0) {
+ mp = copy(p, length(p));
+ chsign(mp);
+ sign = ~sign;
+ }
+ }
+ fsfile(q);
+ mq = q;
+ if (sfbeg(q) == 0) {
+ if (sbackc(q) < 0) {
+ mq = copy(q, length(q));
+ chsign(mq);
+ sign = ~sign;
+ }
+ }
+ mr = salloc(length(mp) + length(mq));
+ zero(mr);
+ rewind(mq);
+ while (sfeof(mq) == 0) {
+ cq = sgetc(mq);
+ rewind(mp);
+ rewind(mr);
+ mr->rd += offset;
+ carry = 0;
+ while (sfeof(mp) == 0) {
+ cp = sgetc(mp);
+ mcr = sfeof(mr) ? 0 : slookc(mr);
+ mt = cp * cq + carry + mcr;
+ carry = mt / 100;
+ salterc(mr, mt % 100);
+ }
+ offset++;
+ if (carry != 0) {
+ mcr = sfeof(mr) ? 0 : slookc(mr);
+ salterc(mr, mcr + carry);
+ }
+ }
+ if (sign < 0) {
+ chsign(mr);
+ }
+ if (mp != p)
+ release(mp);
+ if (mq != q)
+ release(mq);
+ return (mr);
+}
+
+void chsign(struct blk *p)
+{
+ register int carry;
+ register char ct;
+
+ carry = 0;
+ rewind(p);
+ while (sfeof(p) == 0) {
+ ct = 100 - slookc(p) - carry;
+ carry = 1;
+ if (ct >= 100) {
+ ct -= 100;
+ carry = 0;
+ }
+ salterc(p, ct);
+ }
+ if (carry != 0) {
+ sputc(p, -1);
+ fsfile(p);
+ sbackc(p);
+ ct = sbackc(p);
+ if (ct == 99) {
+ truncate(p);
+ sputc(p, -1);
+ }
+ } else {
+ fsfile(p);
+ ct = sbackc(p);
+ if (ct == 0)
+ truncate(p);
+ }
+ return;
+}
+
+int readc(void)
+{
+ loop:
+ if ((readptr != &readstk[0]) && (*readptr != 0)) {
+ if (sfeof(*readptr) == 0)
+ return (lastchar = sgetc(*readptr));
+ release(*readptr);
+ readptr--;
+ goto loop;
+ }
+ lastchar = getc(curfile);
+ if (lastchar != EOF)
+ return (lastchar);
+ if (readptr != &readptr[0]) {
+ readptr--;
+ if (*readptr == 0)
+ curfile = stdin;
+ goto loop;
+ }
+ if (curfile != stdin) {
+ fclose(curfile);
+ curfile = stdin;
+ goto loop;
+ }
+ exit(0);
+}
+
+void unreadc(char c)
+{
+
+ if ((readptr != &readstk[0]) && (*readptr != 0)) {
+ sungetc(*readptr, c);
+ } else
+ ungetc(c, curfile);
+ return;
+}
+
+void binop(char c)
+{
+ register struct blk *r;
+
+ switch (c) {
+ case '+':
+ r = add(arg1, arg2);
+ break;
+ case '*':
+ r = mult(arg1, arg2);
+ break;
+ case '/':
+ r = div(arg1, arg2);
+ break;
+ }
+ release(arg1);
+ release(arg2);
+ sputc(r, savk);
+ pushp(r);
+ return;
+}
+
+void print(struct blk *hptr)
+{
+ int sc;
+ register struct blk *p, *q, *dec;
+ int dig, dout, ct;
+
+ rewind(hptr);
+ while (sfeof(hptr) == 0) {
+ if (sgetc(hptr) > 99) {
+ rewind(hptr);
+ while (sfeof(hptr) == 0) {
+ printf("%c", sgetc(hptr));
+ }
+ printf("\n");
+ return;
+ }
+ }
+ fsfile(hptr);
+ sc = sbackc(hptr);
+ if (sfbeg(hptr) != 0) {
+ printf("0\n");
+ return;
+ }
+ count = ll;
+ p = copy(hptr, length(hptr));
+ sunputc(p);
+ fsfile(p);
+ if (sbackc(p) < 0) {
+ chsign(p);
+ OUTC('-');
+ }
+ if ((obase == 0) || (obase == -1)) {
+ oneot(p, sc, 'd');
+ return;
+ }
+ if (obase == 1) {
+ oneot(p, sc, '1');
+ return;
+ }
+ if (obase == 10) {
+ tenot(p, sc);
+ return;
+ }
+ create(strptr);
+ dig = log10 * sc;
+ dout = ((dig / 10) + dig) / logo;
+ dec = getdec(p, sc);
+ p = removc(p, sc);
+ while (length(p) != 0) {
+ q = div(p, basptr);
+ release(p);
+ p = q;
+ (*outdit) (rem, 0);
+ }
+ release(p);
+ fsfile(strptr);
+ while (sfbeg(strptr) == 0)
+ OUTC(sbackc(strptr));
+ if (sc == 0) {
+ release(dec);
+ printf("\n");
+ return;
+ }
+ create(strptr);
+ OUTC('.');
+ ct = 0;
+ do {
+ q = mult(basptr, dec);
+ release(dec);
+ dec = getdec(q, sc);
+ p = removc(q, sc);
+ (*outdit) (p, 1);
+ } while (++ct < dout);
+ release(dec);
+ rewind(strptr);
+ while (sfeof(strptr) == 0)
+ OUTC(sgetc(strptr));
+ printf("\n");
+ return;
+}
+
+struct blk *getdec(struct blk *p, int sc)
+{
+ int cc;
+ register struct blk *q, *t, *s;
+
+ rewind(p);
+ if (length(p) * 2 < sc) {
+ q = copy(p, length(p));
+ return (q);
+ }
+ q = salloc(length(p));
+ while (sc >= 1) {
+ sputc(q, sgetc(p));
+ sc -= 2;
+ }
+ if (sc != 0) {
+ t = mult(q, tenptr);
+ s = salloc(cc = length(q));
+ release(q);
+ rewind(t);
+ while (cc-- > 0)
+ sputc(s, sgetc(t));
+ sputc(s, 0);
+ release(t);
+ t = div(s, tenptr);
+ release(s);
+ release(rem);
+ return (t);
+ }
+ return (q);
+}
+
+void tenot(struct blk *p, int sc)
+{
+ register int c, f;
+
+ fsfile(p);
+ f = 0;
+ while ((sfbeg(p) == 0) && ((p->rd - p->beg - 1) * 2 >= sc)) {
+ c = sbackc(p);
+ if ((c < 10) && (f == 1))
+ printf("0%d", c);
+ else
+ printf("%d", c);
+ f = 1;
+ TEST2;
+ }
+ if (sc == 0) {
+ printf("\n");
+ release(p);
+ return;
+ }
+ if ((p->rd - p->beg) * 2 > sc) {
+ c = sbackc(p);
+ printf("%d.", c / 10);
+ TEST2;
+ OUTC(c % 10 + '0');
+ sc--;
+ } else {
+ OUTC('.');
+ }
+ if (sc > (p->rd - p->beg) * 2) {
+ while (sc > (p->rd - p->beg) * 2) {
+ OUTC('0');
+ sc--;
+ }
+ }
+ while (sc > 1) {
+ c = sbackc(p);
+ if (c < 10)
+ printf("0%d", c);
+ else
+ printf("%d", c);
+ sc -= 2;
+ TEST2;
+ }
+ if (sc == 1) {
+ OUTC(sbackc(p) / 10 + '0');
+ }
+ printf("\n");
+ release(p);
+ return;
+}
+
+void oneot(struct blk *p, int sc, char ch)
+{
+ register struct blk *q;
+
+ q = removc(p, sc);
+ create(strptr);
+ sputc(strptr, -1);
+ while (length(q) > 0) {
+ p = add(strptr, q);
+ release(q);
+ q = p;
+ OUTC(ch);
+ }
+ release(q);
+ printf("\n");
+ return;
+}
+
+void hexot(struct blk *p, int flg)
+{
+ register int c;
+ rewind(p);
+ if (sfeof(p) != 0) {
+ sputc(strptr, '0');
+ release(p);
+ return;
+ }
+ c = sgetc(p);
+ release(p);
+ if (c >= 16) {
+ printf("hex digit > 16");
+ return;
+ }
+ sputc(strptr, c < 10 ? c + '0' : c - 10 + 'A');
+ return;
+}
+
+void bigot(struct blk *p, int flg)
+{
+ register struct blk *t, *q;
+ register int l;
+ int neg;
+
+ if (flg == 1)
+ t = salloc(0);
+ else {
+ t = strptr;
+ l = length(strptr) + fw - 1;
+ }
+ neg = 0;
+ if (length(p) != 0) {
+ fsfile(p);
+ if (sbackc(p) < 0) {
+ neg = 1;
+ chsign(p);
+ }
+ while (length(p) != 0) {
+ q = div(p, tenptr);
+ release(p);
+ p = q;
+ rewind(rem);
+ sputc(t, sfeof(rem) ? '0' : sgetc(rem) + '0');
+ release(rem);
+ }
+ }
+ release(p);
+ if (flg == 1) {
+ l = fw1 - length(t);
+ if (neg != 0) {
+ l--;
+ sputc(strptr, '-');
+ }
+ fsfile(t);
+ while (l-- > 0)
+ sputc(strptr, '0');
+ while (sfbeg(t) == 0)
+ sputc(strptr, sbackc(t));
+ release(t);
+ } else {
+ l -= length(strptr);
+ while (l-- > 0)
+ sputc(strptr, '0');
+ if (neg != 0) {
+ sunputc(strptr);
+ sputc(strptr, '-');
+ }
+ }
+ sputc(strptr, ' ');
+ return;
+}
+
+struct blk *add(struct blk *a1, struct blk *a2)
+{
+ register struct blk *p;
+ register int carry, n;
+ int size;
+ int c, n1, n2;
+
+ size = length(a1) > length(a2) ? length(a1) : length(a2);
+ p = salloc(size);
+ rewind(a1);
+ rewind(a2);
+ carry = 0;
+ while (--size >= 0) {
+ n1 = sfeof(a1) ? 0 : sgetc(a1);
+ n2 = sfeof(a2) ? 0 : sgetc(a2);
+ n = n1 + n2 + carry;
+ if (n >= 100) {
+ carry = 1;
+ n -= 100;
+ } else if (n < 0) {
+ carry = -1;
+ n += 100;
+ } else
+ carry = 0;
+ sputc(p, n);
+ }
+ if (carry != 0)
+ sputc(p, carry);
+ fsfile(p);
+ if (sfbeg(p) == 0) {
+ while (sfbeg(p) == 0 && (c = sbackc(p)) == 0);
+ if (c != 0)
+ salterc(p, c);
+ truncate(p);
+ }
+ fsfile(p);
+ if (sfbeg(p) == 0 && sbackc(p) == -1) {
+ while ((c = sbackc(p)) == 99) {
+ if (c == EOF)
+ break;
+ }
+ sgetc(p);
+ salterc(p, -1);
+ truncate(p);
+ }
+ return (p);
+}
+
+int eqk(void)
+{
+ register struct blk *p, *q;
+ register int skp;
+ int skq;
+
+ p = pop();
+ EMPTYS;
+ q = pop();
+ EMPTYSR(p);
+ skp = sunputc(p);
+ skq = sunputc(q);
+ if (skp == skq) {
+ arg1 = p;
+ arg2 = q;
+ savk = skp;
+ return (0);
+ } else if (skp < skq) {
+ savk = skq;
+ p = add0(p, skq - skp);
+ } else {
+ savk = skp;
+ q = add0(q, skp - skq);
+ }
+ arg1 = p;
+ arg2 = q;
+ return (0);
+}
+
+struct blk *removc(struct blk *p, int n)
+{
+ register struct blk *q, *r;
+
+ rewind(p);
+ while (n > 1) {
+ sgetc(p);
+ n -= 2;
+ }
+ q = salloc(2);
+ while (sfeof(p) == 0)
+ sputc(q, sgetc(p));
+ if (n == 1) {
+ r = div(q, tenptr);
+ release(q);
+ release(rem);
+ q = r;
+ }
+ release(p);
+ return (q);
+}
+
+struct blk *scalint(struct blk *p)
+{
+ register int n;
+ n = sunputc(p);
+ p = removc(p, n);
+ return (p);
+}
+
+struct blk *scale(struct blk *p, int n)
+{
+ register struct blk *q, *s, *t;
+
+ t = add0(p, n);
+ q = salloc(1);
+ sputc(q, n);
+ s = exp(inbas, q);
+ release(q);
+ q = div(t, s);
+ release(t);
+ release(s);
+ release(rem);
+ sputc(q, n);
+ return (q);
+}
+
+int subt(void)
+{
+ arg1 = pop();
+ EMPTYS;
+ savk = sunputc(arg1);
+ chsign(arg1);
+ sputc(arg1, savk);
+ pushp(arg1);
+ if (eqk() != 0)
+ return (1);
+ binop('+');
+ return (0);
+}
+
+int command(void)
+{
+ int c;
+ char line[100], *sl;
+ void (*savint) (int);
+ pid_t pid, rpid;
+ int retcode;
+
+ switch (c = readc()) {
+ case '<':
+ return (cond(NL));
+ case '>':
+ return (cond(NG));
+ case '=':
+ return (cond(NE));
+ default:
+ sl = line;
+ *sl++ = c;
+ while ((c = readc()) != '\n')
+ *sl++ = c;
+ *sl = 0;
+ if ((pid = fork()) == 0) {
+ execl("/bin/sh", "sh", "-c", line, 0);
+ exit(0100);
+ }
+ savint = signal(SIGINT, SIG_IGN);
+ while ((rpid = wait(&retcode)) != pid && rpid != -1);
+ signal(SIGINT, savint);
+ printf("!\n");
+ return (0);
+ }
+}
+
+int cond(char c)
+{
+ register struct blk *p;
+ register char cc;
+
+ if (subt() != 0)
+ return (1);
+ p = pop();
+ sunputc(p);
+ if (length(p) == 0) {
+ release(p);
+ if (c == '<' || c == '>' || c == NE) {
+ readc();
+ return (0);
+ }
+ load();
+ return (1);
+ } else {
+ if (c == '=') {
+ release(p);
+ readc();
+ return (0);
+ }
+ }
+ if (c == NE) {
+ release(p);
+ load();
+ return (1);
+ }
+ fsfile(p);
+ cc = sbackc(p);
+ release(p);
+ if ((cc < 0 && (c == '<' || c == NG)) ||
+ (cc > 0) && (c == '>' || c == NL)) {
+ readc();
+ return (0);
+ }
+ load();
+ return (1);
+}
+
+void load(void)
+{
+ register int c;
+ register struct blk *p, *q;
+ struct blk *t, *s;
+ c = readc() & 0377;
+ sptr = stable[c];
+ if (sptr != 0) {
+ p = sptr->val;
+ if (c >= ARRAYST) {
+ q = salloc(length(p));
+ rewind(p);
+ while (sfeof(p) == 0) {
+ s = getwd(p);
+ if (s == 0) {
+ putwd(q, (struct blk *) NULL);
+ } else {
+ t = copy(s, length(s));
+ putwd(q, t);
+ }
+ }
+ pushp(q);
+ } else {
+ q = copy(p, length(p));
+ pushp(q);
+ }
+ } else {
+ q = salloc(1);
+ sputc(q, 0);
+ pushp(q);
+ }
+ return;
+}
+
+int log2(long n)
+{
+ register int i;
+
+ if (n == 0)
+ return (0);
+ i = 31;
+ if (n < 0)
+ return (i);
+ while ((n = n << 1) > 0)
+ i--;
+ return (--i);
+}
+
+struct blk *salloc(int size)
+{
+ register struct blk *hdr;
+ register char *ptr;
+ all++;
+ nbytes += size;
+ ptr = malloc((unsigned) size);
+ if (ptr == 0) {
+ garbage("salloc");
+ if ((ptr = malloc((unsigned) size)) == 0)
+ ospace("salloc");
+ }
+ if ((hdr = hfree) == 0)
+ hdr = morehd();
+ hfree = (struct blk *) hdr->rd;
+ hdr->rd = hdr->wt = hdr->beg = ptr;
+ hdr->last = ptr + size;
+ return (hdr);
+}
+
+struct blk *morehd(void)
+{
+ register struct blk *h, *kk;
+ headmor++;
+ nbytes += HEADSZ;
+ hfree = h = (struct blk *) malloc(HEADSZ);
+ if (hfree == 0) {
+ garbage("morehd");
+ if ((hfree = h = (struct blk *) malloc(HEADSZ)) == 0)
+ ospace("headers");
+ }
+ kk = h;
+ while (h < hfree + (HEADSZ / BLK))
+ (h++)->rd = (char *) ++kk;
+ (--h)->rd = 0;
+ return (hfree);
+}
+
+/*
+sunputc(struct blk *hptr)
+{
+ hptr->wt--;
+ hptr->rd = hptr->wt;
+ return(*hptr->wt);
+}
+*/
+struct blk *copy(struct blk *hptr, int size)
+{
+ register struct blk *hdr;
+ register unsigned sz;
+ register char *ptr;
+
+ all++;
+ nbytes += size;
+ sz = length(hptr);
+ ptr = nalloc(hptr->beg, (unsigned) size);
+ if (ptr == 0) {
+ garbage("copy");
+ if ((ptr = nalloc(hptr->beg, (unsigned) size)) == NULL) {
+ printf("copy size %d\n", size);
+ ospace("copy");
+ }
+ }
+ if ((hdr = hfree) == 0)
+ hdr = morehd();
+ hfree = (struct blk *) hdr->rd;
+ hdr->rd = hdr->beg = ptr;
+ hdr->last = ptr + size;
+ hdr->wt = ptr + sz;
+ ptr = hdr->wt;
+ while (ptr < hdr->last)
+ *ptr++ = '\0';
+ return (hdr);
+}
+
+void sdump(char *s1, struct blk *hptr)
+{
+ char *p;
+ printf("%s %o rd %o wt %o beg %o last %o\n", s1, hptr, hptr->rd,
+ hptr->wt, hptr->beg, hptr->last);
+ p = hptr->beg;
+ while (p < hptr->wt)
+ printf("%d ", *p++);
+ printf("\n");
+}
+
+void seekc(struct blk *hptr, int n)
+{
+ char *nn, *p;
+
+ nn = hptr->beg + n;
+ if (nn > hptr->last) {
+ nbytes += nn - hptr->last;
+ free(hptr->beg);
+ p = realloc(hptr->beg, (unsigned) n);
+ if (p == 0) {
+ hptr->beg =
+ realloc(hptr->beg,
+ (unsigned) (hptr->last - hptr->beg));
+ garbage("seekc");
+ if ((p = realloc(hptr->beg, (unsigned) n)) == 0)
+ ospace("seekc");
+ }
+ hptr->beg = p;
+ hptr->wt = hptr->last = hptr->rd = p + n;
+ return;
+ }
+ hptr->rd = nn;
+ if (nn > hptr->wt)
+ hptr->wt = nn;
+ return;
+}
+
+void salterwd(struct wblk *hptr, struct blk *n)
+{
+ if (hptr->rdw == hptr->lastw)
+ more((struct blk *) hptr);
+ *hptr->rdw++ = n;
+ if (hptr->rdw > hptr->wtw)
+ hptr->wtw = hptr->rdw;
+ return;
+}
+
+void more(struct blk *hptr)
+{
+ register unsigned size;
+ register char *p;
+
+ if ((size = (hptr->last - hptr->beg) * 2) == 0)
+ size = 1;
+ nbytes += size / 2;
+ free(hptr->beg);
+ p = realloc(hptr->beg, (unsigned) size);
+ if (p == 0) {
+ hptr->beg =
+ realloc(hptr->beg,
+ (unsigned) (hptr->last - hptr->beg));
+ garbage("more");
+ if ((p = realloc(hptr->beg, size)) == 0)
+ ospace("more");
+ }
+ hptr->rd = hptr->rd - hptr->beg + p;
+ hptr->wt = hptr->wt - hptr->beg + p;
+ hptr->beg = p;
+ hptr->last = p + size;
+ return;
+}
+
+void ospace(char *s)
+{
+ printf("out of space: %s\n", s);
+ printf("all %ld rel %ld headmor %ld\n", all, rel, headmor);
+ printf("nbytes %ld\n", nbytes);
+ sdump("stk", *stkptr);
+ abort();
+}
+
+void garbage(char *s)
+{
+ int i;
+ struct blk *p, *q;
+ struct sym *tmps;
+ int ct;
+
+/* printf("got to garbage %s\n",s); */
+ for (i = 0; i < TBLSZ; i++) {
+ tmps = stable[i];
+ if (tmps != 0) {
+ if (i < ARRAYST) {
+ do {
+ p = tmps->val;
+ if (((int) p->beg & 01) != 0) {
+ printf("string %o\n", i);
+ sdump("odd beg", p);
+ }
+ redef(p);
+ tmps = tmps->next;
+ } while (tmps != 0);
+ continue;
+ } else {
+ do {
+ p = tmps->val;
+ rewind(p);
+ ct = 0;
+ while ((q = getwd(p)) != NULL) {
+ ct++;
+ if (q != 0) {
+ if (((int) q->
+ beg & 01) !=
+ 0) {
+ printf
+ ("array %o elt %d odd\n",
+ i -
+ ARRAYST,
+ ct);
+ printf
+ ("tmps %o p %o\n",
+ tmps,
+ p);
+ sdump
+ ("elt",
+ q);
+ }
+ redef(q);
+ }
+ }
+ tmps = tmps->next;
+ } while (tmps != 0);
+ }
+ }
+ }
+}
+
+void redef(struct blk *p)
+{
+ register offset;
+ register char *newp;
+
+ if ((int) p->beg & 01) {
+ printf("odd ptr %o hdr %o\n", p->beg, p);
+ ospace("redef-bad");
+ }
+ free(p->beg);
+ free(dummy);
+ dummy = malloc(1);
+ if (dummy == NULL)
+ ospace("dummy");
+ newp = realloc(p->beg, (unsigned) (p->last - p->beg));
+ if (newp == NULL)
+ ospace("redef");
+ offset = newp - p->beg;
+ p->beg = newp;
+ p->rd += offset;
+ p->wt += offset;
+ p->last += offset;
+}
+
+void release(struct blk *p)
+{
+ rel++;
+ nbytes -= p->last - p->beg;
+ p->rd = (char *) hfree;
+ hfree = p;
+ free(p->beg);
+}
+
+struct blk *getwd(struct blk *p)
+{
+ register struct wblk *wp;
+
+ wp = (struct wblk *) p;
+ if (wp->rdw == wp->wtw)
+ return (NULL);
+ return (*wp->rdw++);
+}
+
+void putwd(struct blk *p, struct blk *c)
+{
+ register struct wblk *wp;
+
+ wp = (struct wblk *) p;
+ if (wp->wtw == wp->lastw)
+ more(p);
+ *wp->wtw++ = c;
+}
+
+struct blk *lookwd(struct blk *p)
+{
+ register struct wblk *wp;
+
+ wp = (struct wblk *) p;
+ if (wp->rdw == wp->wtw)
+ return (NULL);
+ return (*wp->rdw);
+}
+
+char *nalloc(char *p, unsigned nbytes)
+{
+ char *q, *r;
+ q = r = malloc(nbytes);
+ if (q == 0)
+ return (0);
+ while (nbytes--)
+ *q++ = *p++;
+ return (r);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+
+#define BIG 32767
+#define LCASE 01
+#define UCASE 02
+#define SWAB 04
+#define NERR 010
+#define SYNC 020
+int cflag;
+int fflag;
+int skip;
+int seekn;
+int count;
+int files = 1;
+char *string;
+char *ifile;
+char *ofile;
+char *ibuf;
+char *obuf;
+int ibs = 512;
+int obs = 512;
+int bs;
+int cbs;
+int ibc;
+int obc;
+int cbc;
+int nifr;
+int nipr;
+int nofr;
+int nopr;
+int ntrunc;
+int ibf;
+int obf;
+char *op;
+int nspace;
+const char etoa[] = {
+ 0000,0001,0002,0003,0234,0011,0206,0177,
+ 0227,0215,0216,0013,0014,0015,0016,0017,
+ 0020,0021,0022,0023,0235,0205,0010,0207,
+ 0030,0031,0222,0217,0034,0035,0036,0037,
+ 0200,0201,0202,0203,0204,0012,0027,0033,
+ 0210,0211,0212,0213,0214,0005,0006,0007,
+ 0220,0221,0026,0223,0224,0225,0226,0004,
+ 0230,0231,0232,0233,0024,0025,0236,0032,
+ 0040,0240,0241,0242,0243,0244,0245,0246,
+ 0247,0250,0133,0056,0074,0050,0053,0041,
+ 0046,0251,0252,0253,0254,0255,0256,0257,
+ 0260,0261,0135,0044,0052,0051,0073,0136,
+ 0055,0057,0262,0263,0264,0265,0266,0267,
+ 0270,0271,0174,0054,0045,0137,0076,0077,
+ 0272,0273,0274,0275,0276,0277,0300,0301,
+ 0302,0140,0072,0043,0100,0047,0075,0042,
+ 0303,0141,0142,0143,0144,0145,0146,0147,
+ 0150,0151,0304,0305,0306,0307,0310,0311,
+ 0312,0152,0153,0154,0155,0156,0157,0160,
+ 0161,0162,0313,0314,0315,0316,0317,0320,
+ 0321,0176,0163,0164,0165,0166,0167,0170,
+ 0171,0172,0322,0323,0324,0325,0326,0327,
+ 0330,0331,0332,0333,0334,0335,0336,0337,
+ 0340,0341,0342,0343,0344,0345,0346,0347,
+ 0173,0101,0102,0103,0104,0105,0106,0107,
+ 0110,0111,0350,0351,0352,0353,0354,0355,
+ 0175,0112,0113,0114,0115,0116,0117,0120,
+ 0121,0122,0356,0357,0360,0361,0362,0363,
+ 0134,0237,0123,0124,0125,0126,0127,0130,
+ 0131,0132,0364,0365,0366,0367,0370,0371,
+ 0060,0061,0062,0063,0064,0065,0066,0067,
+ 0070,0071,0372,0373,0374,0375,0376,0377,
+};
+const char atoe[] = {
+ 0000,0001,0002,0003,0067,0055,0056,0057,
+ 0026,0005,0045,0013,0014,0015,0016,0017,
+ 0020,0021,0022,0023,0074,0075,0062,0046,
+ 0030,0031,0077,0047,0034,0035,0036,0037,
+ 0100,0117,0177,0173,0133,0154,0120,0175,
+ 0115,0135,0134,0116,0153,0140,0113,0141,
+ 0360,0361,0362,0363,0364,0365,0366,0367,
+ 0370,0371,0172,0136,0114,0176,0156,0157,
+ 0174,0301,0302,0303,0304,0305,0306,0307,
+ 0310,0311,0321,0322,0323,0324,0325,0326,
+ 0327,0330,0331,0342,0343,0344,0345,0346,
+ 0347,0350,0351,0112,0340,0132,0137,0155,
+ 0171,0201,0202,0203,0204,0205,0206,0207,
+ 0210,0211,0221,0222,0223,0224,0225,0226,
+ 0227,0230,0231,0242,0243,0244,0245,0246,
+ 0247,0250,0251,0300,0152,0320,0241,0007,
+ 0040,0041,0042,0043,0044,0025,0006,0027,
+ 0050,0051,0052,0053,0054,0011,0012,0033,
+ 0060,0061,0032,0063,0064,0065,0066,0010,
+ 0070,0071,0072,0073,0004,0024,0076,0341,
+ 0101,0102,0103,0104,0105,0106,0107,0110,
+ 0111,0121,0122,0123,0124,0125,0126,0127,
+ 0130,0131,0142,0143,0144,0145,0146,0147,
+ 0150,0151,0160,0161,0162,0163,0164,0165,
+ 0166,0167,0170,0200,0212,0213,0214,0215,
+ 0216,0217,0220,0232,0233,0234,0235,0236,
+ 0237,0240,0252,0253,0254,0255,0256,0257,
+ 0260,0261,0262,0263,0264,0265,0266,0267,
+ 0270,0271,0272,0273,0274,0275,0276,0277,
+ 0312,0313,0314,0315,0316,0317,0332,0333,
+ 0334,0335,0336,0337,0352,0353,0354,0355,
+ 0356,0357,0372,0373,0374,0375,0376,0377,
+};
+const char atoibm[] =
+{
+ 0000,0001,0002,0003,0067,0055,0056,0057,
+ 0026,0005,0045,0013,0014,0015,0016,0017,
+ 0020,0021,0022,0023,0074,0075,0062,0046,
+ 0030,0031,0077,0047,0034,0035,0036,0037,
+ 0100,0132,0177,0173,0133,0154,0120,0175,
+ 0115,0135,0134,0116,0153,0140,0113,0141,
+ 0360,0361,0362,0363,0364,0365,0366,0367,
+ 0370,0371,0172,0136,0114,0176,0156,0157,
+ 0174,0301,0302,0303,0304,0305,0306,0307,
+ 0310,0311,0321,0322,0323,0324,0325,0326,
+ 0327,0330,0331,0342,0343,0344,0345,0346,
+ 0347,0350,0351,0255,0340,0275,0137,0155,
+ 0171,0201,0202,0203,0204,0205,0206,0207,
+ 0210,0211,0221,0222,0223,0224,0225,0226,
+ 0227,0230,0231,0242,0243,0244,0245,0246,
+ 0247,0250,0251,0300,0117,0320,0241,0007,
+ 0040,0041,0042,0043,0044,0025,0006,0027,
+ 0050,0051,0052,0053,0054,0011,0012,0033,
+ 0060,0061,0032,0063,0064,0065,0066,0010,
+ 0070,0071,0072,0073,0004,0024,0076,0341,
+ 0101,0102,0103,0104,0105,0106,0107,0110,
+ 0111,0121,0122,0123,0124,0125,0126,0127,
+ 0130,0131,0142,0143,0144,0145,0146,0147,
+ 0150,0151,0160,0161,0162,0163,0164,0165,
+ 0166,0167,0170,0200,0212,0213,0214,0215,
+ 0216,0217,0220,0232,0233,0234,0235,0236,
+ 0237,0240,0252,0253,0254,0255,0256,0257,
+ 0260,0261,0262,0263,0264,0265,0266,0267,
+ 0270,0271,0272,0273,0274,0275,0276,0277,
+ 0312,0313,0314,0315,0316,0317,0332,0333,
+ 0334,0335,0336,0337,0352,0353,0354,0355,
+ 0356,0357,0372,0373,0374,0375,0376,0377,
+};
+
+
+void stats(void)
+{
+
+ fprintf(stderr,"%u+%u records in\n", nifr, nipr);
+ fprintf(stderr,"%u+%u records out\n", nofr, nopr);
+ if(ntrunc)
+ fprintf(stderr,"%u truncated records\n", ntrunc);
+}
+
+void term(void)
+{
+
+ stats();
+ exit(0);
+}
+
+void sigterm(int sig)
+{
+ term();
+}
+
+void flsh(void)
+{
+ register c;
+
+ if(obc) {
+ if(obc == obs)
+ nofr++; else
+ nopr++;
+ c = write(obf, obuf, obc);
+ if(c != obc) {
+ perror("write");
+ term();
+ }
+ obc = 0;
+ }
+}
+
+int match(char *s)
+{
+ register char *cs;
+
+ cs = string;
+ while(*cs++ == *s)
+ if(*s++ == '\0')
+ goto true;
+ if(*s != '\0')
+ return(0);
+
+true:
+ cs--;
+ string = cs;
+ return(1);
+}
+
+long number(int big)
+{
+ register char *cs;
+ long n;
+
+ cs = string;
+ n = 0;
+ while(*cs >= '0' && *cs <= '9')
+ n = n*10 + *cs++ - '0';
+ for(;;)
+ switch(*cs++) {
+
+ case 'm':
+ n *= 1024L * 1024L;
+ continue;
+ case 'k':
+ n *= 1024;
+ continue;
+
+ case 'w':
+ n *= sizeof(int);
+ continue;
+
+ case 'b':
+ n *= 512;
+ continue;
+
+ case '*':
+ case 'x':
+ string = cs;
+ n *= number(BIG);
+
+ case '\0':
+ if (n>=big || n<0) {
+ fprintf(stderr, "dd: argument %D out of range\n", n);
+ exit(1);
+ }
+ return(n);
+ }
+ /* never gets here */
+}
+
+void null(int c)
+{
+
+ *op = c;
+ op++;
+ if(++obc >= obs) {
+ flsh();
+ op = obuf;
+ }
+}
+
+void cnull(int cc)
+{
+ register int c;
+
+ c = cc;
+ if(cflag&UCASE && c>='a' && c<='z')
+ c += 'A'-'a';
+ if(cflag&LCASE && c>='A' && c<='Z')
+ c += 'a'-'A';
+ null(c);
+}
+
+void ascii(int cc)
+{
+ register int c;
+
+ c = etoa[cc] & 0377;
+ if(cbs == 0) {
+ cnull(c);
+ return;
+ }
+ if(c == ' ') {
+ nspace++;
+ goto out;
+ }
+ while(nspace > 0) {
+ null(' ');
+ nspace--;
+ }
+ cnull(c);
+
+out:
+ if(++cbc >= cbs) {
+ null('\n');
+ cbc = 0;
+ nspace = 0;
+ }
+}
+
+void ebcdic(int cc)
+{
+ register int c;
+
+ c = cc;
+ if(cflag&UCASE && c>='a' && c<='z')
+ c += 'A'-'a';
+ if(cflag&LCASE && c>='A' && c<='Z')
+ c += 'a'-'A';
+ c = atoe[c] & 0377;
+ if(cbs == 0) {
+ null(c);
+ return;
+ }
+ if(cc == '\n') {
+ while(cbc < cbs) {
+ null(atoe[' ']);
+ cbc++;
+ }
+ cbc = 0;
+ return;
+ }
+ if(cbc == cbs)
+ ntrunc++;
+ cbc++;
+ if(cbc <= cbs)
+ null(c);
+}
+
+void ibm(int cc)
+{
+ register int c;
+
+ c = cc;
+ if(cflag&UCASE && c>='a' && c<='z')
+ c += 'A'-'a';
+ if(cflag&LCASE && c>='A' && c<='Z')
+ c += 'a'-'A';
+ c = atoibm[c] & 0377;
+ if(cbs == 0) {
+ null(c);
+ return;
+ }
+ if(cc == '\n') {
+ while(cbc < cbs) {
+ null(atoibm[' ']);
+ cbc++;
+ }
+ cbc = 0;
+ return;
+ }
+ if(cbc == cbs)
+ ntrunc++;
+ cbc++;
+ if(cbc <= cbs)
+ null(c);
+}
+
+
+
+int main(int argc, char *argv[])
+{
+ void (*conv)(int);
+ register char *ip;
+ register int c;
+ int a;
+
+ conv = null;
+ for(c=1; c<argc; c++) {
+ string = argv[c];
+ if(match("ibs=")) {
+ ibs = number(BIG);
+ continue;
+ }
+ if(match("obs=")) {
+ obs = number(BIG);
+ continue;
+ }
+ if(match("cbs=")) {
+ cbs = number(BIG);
+ continue;
+ }
+ if (match("bs=")) {
+ bs = number(BIG);
+ continue;
+ }
+ if(match("if=")) {
+ ifile = string;
+ continue;
+ }
+ if(match("of=")) {
+ ofile = string;
+ continue;
+ }
+ if(match("skip=")) {
+ skip = number(BIG);
+ continue;
+ }
+ if(match("seek=")) {
+ seekn = number(BIG);
+ continue;
+ }
+ if(match("count=")) {
+ count = number(BIG);
+ continue;
+ }
+ if(match("files=")) {
+ files = number(BIG);
+ continue;
+ }
+ if(match("conv=")) {
+ cloop:
+ if(match(","))
+ goto cloop;
+ if(*string == '\0')
+ continue;
+ if(match("ebcdic")) {
+ conv = ebcdic;
+ goto cloop;
+ }
+ if(match("ibm")) {
+ conv = ibm;
+ goto cloop;
+ }
+ if(match("ascii")) {
+ conv = ascii;
+ goto cloop;
+ }
+ if(match("lcase")) {
+ cflag |= LCASE;
+ goto cloop;
+ }
+ if(match("ucase")) {
+ cflag |= UCASE;
+ goto cloop;
+ }
+ if(match("swab")) {
+ cflag |= SWAB;
+ goto cloop;
+ }
+ if(match("noerror")) {
+ cflag |= NERR;
+ goto cloop;
+ }
+ if(match("sync")) {
+ cflag |= SYNC;
+ goto cloop;
+ }
+ }
+ fprintf(stderr,"bad arg: %s\n", string);
+ exit(0);
+ }
+ if(conv == null && cflag&(LCASE|UCASE))
+ conv = cnull;
+ if (ifile)
+ ibf = open(ifile, 0);
+ else
+ ibf = dup(0);
+ if(ibf < 0) {
+ fprintf(stderr,"cannot open: %s\n", ifile);
+ exit(0);
+ }
+ if (ofile)
+ obf = creat(ofile, 0666);
+ else
+ obf = dup(1);
+ if(obf < 0) {
+ fprintf(stderr,"cannot create: %s\n", ofile);
+ exit(0);
+ }
+ if (bs) {
+ ibs = obs = bs;
+ if (conv == null)
+ fflag++;
+ }
+ if(ibs == 0 || obs == 0) {
+ fprintf(stderr,"counts: cannot be zero\n");
+ exit(0);
+ }
+ ibuf = sbrk(ibs);
+ if (fflag)
+ obuf = ibuf;
+ else
+ obuf = sbrk(obs);
+ sbrk(64); /* For good measure */
+ if(ibuf == (char *)-1 || obuf == (char *)-1) {
+ fprintf(stderr, "not enough memory\n");
+ exit(0);
+ }
+ ibc = 0;
+ obc = 0;
+ cbc = 0;
+ op = obuf;
+
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, sigterm);
+ while(skip) {
+ read(ibf, ibuf, ibs);
+ skip--;
+ }
+ while(seekn) {
+ lseek(obf, (long)obs, 1);
+ seekn--;
+ }
+
+loop:
+ if(ibc-- == 0) {
+ ibc = 0;
+ if(count==0 || nifr+nipr!=count) {
+ if(cflag&(NERR|SYNC))
+ for(ip=ibuf+ibs; ip>ibuf;)
+ *--ip = 0;
+ ibc = read(ibf, ibuf, ibs);
+ }
+ if(ibc == -1) {
+ perror("read");
+ if((cflag&NERR) == 0) {
+ flsh();
+ term();
+ }
+ ibc = 0;
+ for(c=0; c<ibs; c++)
+ if(ibuf[c] != 0)
+ ibc = c;
+ stats();
+ }
+ if(ibc == 0 && --files<=0) {
+ flsh();
+ term();
+ }
+ if(ibc != ibs) {
+ nipr++;
+ if(cflag&SYNC)
+ ibc = ibs;
+ } else
+ nifr++;
+ ip = ibuf;
+ c = (ibc>>1) & ~1;
+ if(cflag&SWAB && c)
+ do {
+ a = *ip++;
+ ip[-1] = *ip;
+ *ip++ = a;
+ } while(--c);
+ ip = ibuf;
+ if (fflag) {
+ obc = ibc;
+ flsh();
+ ibc = 0;
+ }
+ goto loop;
+ }
+ c = 0;
+ c |= *ip++;
+ c &= 0377;
+ (*conv)(c);
+ goto loop;
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+char *xxxvers = "\nDeroff Version 1.02fuzix 18th March 2015\n";
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Deroff command -- strip troff, eqn, and Tbl sequences from
+a file. Has one flag argument, -w, to cause output one word per line
+rather than in the original format.
+Deroff follows .so and .nx commands, removes contents of macro
+definitions, equations (both .EQ ... .EN and $...$),
+Tbl command sequences, and Troff backslash constructions.
+
+All input is through the C macro; the most recently read character is in c.
+*/
+
+#define C ( (c=getc(infile)) == EOF ? eof() : ((c==ldelim)&&(filesp==files) ? skeqn() : c) )
+#define C1 ( (c=getc(infile)) == EOF ? eof() : c)
+#define SKIP while(C != '\n')
+
+#define YES 1
+#define NO 0
+
+#define NOCHAR -2
+#define SPECIAL 0
+#define APOS 1
+#define DIGIT 2
+#define LETTER 3
+
+int wordflag = NO;
+int inmacro = NO;
+int intable = NO;
+
+char chars[128]; /* SPECIAL, APOS, DIGIT, or LETTER */
+
+char line[512];
+char *lp;
+
+int c;
+int ldelim = NOCHAR;
+int rdelim = NOCHAR;
+
+
+int argc;
+char **argv;
+
+char fname[50];
+FILE *files[15];
+FILE **filesp;
+FILE *infile;
+
+
+extern int eof(void);
+extern void backsl(void);
+
+
+void fatal(const char *s, const char *p)
+{
+ fprintf(stderr, "Deroff: ");
+ fprintf(stderr, s, p);
+ exit(1);
+}
+
+FILE *opn(const char *p)
+{
+ FILE *fd;
+
+ if (p[0] == '-' && p[1] == '\0')
+ fd = stdin;
+ else if ((fd = fopen(p, "r")) == NULL)
+ fatal("Cannot open file %s\n", p);
+
+ return (fd);
+}
+
+
+int skeqn(void)
+{
+ while ((c = getc(infile)) != rdelim)
+ if (c == EOF)
+ c = eof();
+ else if (c == '"')
+ while ((c = getc(infile)) != '"')
+ if (c == EOF)
+ c = eof();
+ else if (c == '\\')
+ if ((c = getc(infile)) == EOF)
+ c = eof();
+ return (c = ' ');
+}
+
+int eof(void)
+{
+ if (infile != stdin)
+ fclose(infile);
+ if (filesp > files)
+ infile = *--filesp;
+ else if (argc > 0) {
+ infile = opn(argv[0]);
+ --argc;
+ ++argv;
+ } else
+ exit(0);
+
+ return (C);
+}
+
+
+
+char *copys(char *s)
+{
+ register char *t, *t0;
+
+ if ((t0 = t = calloc(strlen(s) + 1, sizeof(*t))) == NULL)
+ fatal("Cannot allocate memory", (char *) NULL);
+
+ while (*t++ = *s++);
+ return (t0);
+}
+
+void getfname(void)
+{
+ register char *p;
+ struct chain {
+ struct chain *nextp;
+ char *datap;
+ } *chainblock;
+ register struct chain *q;
+ static struct chain *namechain = NULL;
+
+ while (C == ' ');
+
+ for (p = fname;
+ (*p = c) != '\n' && c != ' ' && c != '\t' && c != '\\'; ++p)
+ C;
+ *p = '\0';
+ while (c != '\n')
+ C;
+
+/* see if this name has already been used */
+
+ for (q = namechain; q; q = q->nextp)
+ if (!strcmp(fname, q->datap)) {
+ fname[0] = '\0';
+ return;
+ }
+
+ q = (struct chain *) calloc(1, sizeof(*chainblock));
+ q->nextp = namechain;
+ q->datap = copys(fname);
+ namechain = q;
+}
+
+void putmac(char *s)
+{
+ register char *t;
+
+ while (*s) {
+ while (*s == ' ' || *s == '\t')
+ putchar(*s++);
+ for (t = s; *t != ' ' && *t != '\t' && *t != '\0'; ++t);
+ if (t > s + 2 && chars[s[0]] == LETTER
+ && chars[s[1]] == LETTER)
+ while (s < t)
+ putchar(*s++);
+ else
+ s = t;
+ }
+ putchar('\n');
+}
+
+
+
+void putwords(int macline)
+{ /* break into words for -w option */
+ register char *p, *p1;
+ int i, nlet;
+
+
+ for (p1 = line;;) {
+ /* skip initial specials ampersands and apostrophes */
+ while (chars[*p1] < DIGIT)
+ if (*p1++ == '\0')
+ return;
+ nlet = 0;
+ for (p = p1; (i = chars[*p]) != SPECIAL; ++p)
+ if (i == LETTER)
+ ++nlet;
+
+ if ((!macline && nlet > 1) /* MDM definition of word */
+ ||(macline && nlet > 2 && chars[p1[0]] == LETTER
+ && chars[p1[1]] == LETTER)) {
+ /* delete trailing ampersands and apostrophes */
+ while (p[-1] == '\'' || p[-1] == '&')
+ --p;
+ while (p1 < p)
+ putchar(*p1++);
+ putchar('\n');
+ } else
+ p1 = p;
+ }
+}
+
+
+void regline(int macline)
+{
+ line[0] = c;
+ lp = line;
+ for (;;) {
+ if (c == '\\') {
+ *lp = ' ';
+ backsl();
+ }
+ if (c == '\n')
+ break;
+ if (intable && c == 'T') {
+ *++lp = C;
+ if (c == '{' || c == '}') {
+ lp[-1] = ' ';
+ *lp = C;
+ }
+ } else
+ *++lp = C;
+ }
+
+ *lp = '\0';
+
+ if (line[0] != '\0')
+ if (wordflag)
+ putwords(macline);
+ else if (macline)
+ putmac(line);
+ else
+ puts(line);
+}
+
+
+
+
+
+
+void macro(void)
+{
+/*
+do { SKIP; }
+ while(C!='.' || C!='.' || C=='.'); /* look for .. */
+ SKIP;
+ inmacro = YES;
+}
+
+
+
+
+void tbl(void)
+{
+ while (C != '.');
+ SKIP;
+ intable = YES;
+}
+
+
+void eqn(void)
+{
+ register int c1, c2;
+
+ SKIP;
+
+ for (;;) {
+ if (C == '.' || c == '\'') {
+ while (C == ' ' || c == '\t');
+ if (c == 'E' && C == 'N') {
+ SKIP;
+ return;
+ }
+ } else if (c == 'd') { /* look for delim */
+ if (C == 'e' && C == 'l')
+ if (C == 'i' && C == 'm') {
+ while (C1 == ' ');
+ if ((c1 = c) == '\n'
+ || (c2 = C1) == '\n'
+ || (c1 == 'o' && c2 == 'f'
+ && C1 == 'f')) {
+ ldelim = NOCHAR;
+ rdelim = NOCHAR;
+ } else {
+ ldelim = c1;
+ rdelim = c2;
+ }
+ }
+ }
+
+ if (c != '\n')
+ SKIP;
+ }
+}
+
+void backsl(void)
+{ /* skip over a complete backslash construction */
+ int bdelim;
+
+ sw:switch (C) {
+ case '"':
+ SKIP;
+ return;
+ case 's':
+ if (C == '\\')
+ backsl();
+ else {
+ while (C >= '0' && c <= '9');
+ ungetc(c, infile);
+ c = '0';
+ }
+ --lp;
+ return;
+
+ case 'f':
+ case 'n':
+ case '*':
+ if (C != '(')
+ return;
+
+ case '(':
+ if (C != '\n')
+ C;
+ return;
+
+ case '$':
+ C; /* discard argument number */
+ return;
+
+ case 'b':
+ case 'x':
+ case 'v':
+ case 'h':
+ case 'w':
+ case 'o':
+ case 'l':
+ case 'L':
+ if ((bdelim = C) == '\n')
+ return;
+ while (C != '\n' && c != bdelim)
+ if (c == '\\')
+ backsl();
+ return;
+
+ case '\\':
+ if (inmacro)
+ goto sw;
+ default:
+ return;
+ }
+}
+
+void comline(void)
+{
+ register int c1, c2;
+
+ while (C == ' ' || c == '\t');
+ if ((c1 = c) == '\n')
+ return;
+ c2 = C;
+ if (c1 == '.' && c2 != '.')
+ inmacro = NO;
+ if (c2 == '\n')
+ return;
+
+ if (c1 == 'E' && c2 == 'Q' && filesp == files)
+ eqn();
+ else if (c1 == 'T' && (c2 == 'S' || c2 == 'C' || c2 == '&')
+ && filesp == files)
+ tbl();
+ else if (c1 == 'T' && c2 == 'E')
+ intable = NO;
+ else if (!inmacro && c1 == 'd' && c2 == 'e')
+ macro();
+ else if (!inmacro && c1 == 'i' && c2 == 'g')
+ macro();
+ else if (!inmacro && c1 == 'a' && c2 == 'm')
+ macro();
+ else if (c1 == 's' && c2 == 'o') {
+ getfname();
+ if (fname[0])
+ infile = *++filesp = opn(fname);
+ } else if (c1 == 'n' && c2 == 'x') {
+ getfname();
+ if (fname[0] == '\0')
+ exit(0);
+ if (infile != stdin)
+ fclose(infile);
+ infile = *filesp = opn(fname);
+ } else if (c1 == 'h' && c2 == 'w') {
+ SKIP;
+ } else {
+ if (c1 == '.' && c2 == '.')
+ while (C == '.');
+ ++inmacro;
+ regline(YES);
+ --inmacro;
+ }
+}
+
+
+void work(void)
+{
+
+ for (;;) {
+ if (C == '.' || c == '\'')
+ comline();
+ else
+ regline(NO);
+ }
+}
+
+
+
+
+int main(int ac, const char *av[])
+{
+ register int i;
+ register char *p;
+ static char onechar[2] = "X";
+
+ argc = ac - 1;
+ argv = av + 1;
+
+ while (argc > 0 && argv[0][0] == '-' && argv[0][1] != '\0') {
+ for (p = argv[0] + 1; *p; ++p)
+ switch (*p) {
+ case 'w':
+ wordflag = YES;
+ break;
+ default:
+ onechar[0] = *p;
+ fatal("Invalid flag %s\n", onechar);
+ }
+ --argc;
+ ++argv;
+ }
+
+ if (argc == 0)
+ infile = stdin;
+ else {
+ infile = opn(argv[0]);
+ --argc;
+ ++argv;
+ }
+
+ files[0] = infile;
+ filesp = &files[0];
+
+ for (i = 'a'; i <= 'z'; ++i)
+ chars[i] = LETTER;
+ for (i = 'A'; i <= 'Z'; ++i)
+ chars[i] = LETTER;
+ for (i = '0'; i <= '9'; ++i)
+ chars[i] = DIGIT;
+ chars['\''] = APOS;
+ chars['&'] = APOS;
+
+ work();
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+/* diff - differential file comparison
+*
+* Uses an algorithm due to Harold Stone, which finds
+* a pair of longest identical subsequences in the two
+* files.
+*
+* The major goal is to generate the match vector J.
+* J[i] is the index of the line in file1 corresponding
+* to line i file0. J[i] = 0 if there is no
+* such line in file1.
+*
+* Lines are hashed so as to work in core. All potential
+* matches are located by sorting the lines of each file
+* on the hash (called value\b\b\b\b\b_____). In particular, this
+* collects the equivalence classes in file1 together.
+* Subroutine equiv\b\b\b\b____ replaces the value of each line in
+* file0 by the index of the first element of its
+* matching equivalence in (the reordered) file1.
+* To save space equiv\b\b\b\b\b_____ squeezes file1 into a single
+* array member\b\b\b\b\b\b______ in which the equivalence classes
+* are simply concatenated, except that their first
+* members are flagged by changing sign.
+*
+* Next the indices that point into member\b\b\b\b\b\b______ are unsorted\b\b\b\b\b\b\b\b_______ into
+* array class\b\b\b\b\b_____ according to the original order of file0.
+*
+* The cleverness lies in routine stone\b\b\b\b\b______. This marches
+* through the lines of file0, developing a vector klist\b\b\b\b\b_____
+* of "k-candidates". At step i a k-candidate is a matched
+* pair of lines x,y (x in file0 y in file1) such that
+* there is a common subsequence of lenght k
+* between the first i lines of file0 and the first y
+* lines of file1, but there is no such subsequence for
+* any smaller y. x is the earliest possible mate to y
+* that occurs in such a subsequence.
+*
+* Whenever any of the members of the equivalence class of
+* lines in file1 matable to a line in file0 has serial number
+* less than the y of some k-candidate, that k-candidate
+* with the smallest such y is replaced. The new
+* k-candidate is chained (via pred\b\b\b\b____) to the current
+* k-1 candidate so that the actual subsequence can
+* be recovered. When a member has serial number greater
+* that the y of all k-candidates, the klist is extended.
+* At the end, the longest subsequence is pulled out
+* and placed in the array J by unravel\b\b\b\b\b\b\b_______.
+*
+* With J in hand, the matches there recorded are
+* check\b\b\b\b\b_____ed against reality to assure that no spurious
+* matches have crept in due to hashing. If they have,
+* they are broken, and "jackpot " is recorded--a harmless
+* matter except that a true match for a spuriously
+* mated line may now be unnecessarily reported as a change.
+*
+* Much of the complexity of the program comes simply
+* from trying to minimize core utilization and
+* maximize the range of doable problems by dynamically
+* allocating what is needed and reusing what is not.
+* The core requirements for problems larger than somewhat
+* are (in words) 2*length(file0) + length(file1) +
+* 3*(number of k-candidates installed), typically about
+* 6n words for files of length n.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#define prints(s) fputs(s,stdout)
+
+#define HALFLONG 16
+#define low(x) (x&((1L<<HALFLONG)-1))
+#define high(x) (x>>HALFLONG)
+FILE *input[2];
+
+struct cand {
+ int x;
+ int y;
+ int pred;
+} cand;
+struct line {
+ int serial;
+ int value;
+} *file[2], line;
+int len[2];
+struct line *sfile[2]; /*shortened by pruning common prefix and suffix */
+int slen[2];
+int pref, suff; /*length of prefix and suffix */
+int *class; /*will be overlaid on file[0] */
+int *member; /*will be overlaid on file[1] */
+int *klist; /*will be overlaid on file[0] after class */
+struct cand *clist; /* merely a free storage pot for candidates */
+int clen = 0;
+int *J; /*will be overlaid on class */
+long *ixold; /*will be overlaid on klist */
+long *ixnew; /*will be overlaid on file[1] */
+int opt; /* -1,0,1 = -e,normal,-f */
+int status = 2;
+int anychange = 0;
+char *empty = "";
+int bflag;
+
+char *tempfile; /*used when comparing against std input */
+char *dummy; /*used in resetting storage search ptr */
+
+void done(void)
+{
+ unlink(tempfile);
+ exit(status);
+}
+
+void sdone(int sig)
+{
+ done();
+}
+
+void mesg(char *s, char *t)
+{
+ fprintf(stderr, "diff: %s%s\n", s, t);
+}
+
+void noroom(void)
+{
+ mesg("files too big, try -h\n", empty);
+ done();
+}
+
+char *talloc(size_t n)
+{
+ register char *p;
+ p = malloc(n);
+ if (p != NULL)
+ return (p);
+ noroom();
+}
+
+char *ralloc(char *p, size_t n)
+{
+ char *q = realloc(p, n);
+ if (q == NULL)
+ noroom();
+ return (q);
+}
+
+void sort(struct line *a, int n)
+{ /*shellsort CACM #201 */
+ struct line w;
+ register int j, m;
+ struct line *ai;
+ register struct line *aim;
+ int k;
+ for (j = 1; j <= n; j *= 2)
+ m = 2 * j - 1;
+ for (m /= 2; m != 0; m /= 2) {
+ k = n - m;
+ for (j = 1; j <= k; j++) {
+ for (ai = &a[j]; ai > a; ai -= m) {
+ aim = &ai[m];
+ if (aim < ai)
+ break; /*wraparound */
+ if (aim->value > ai[0].value ||
+ aim->value == ai[0].value &&
+ aim->serial > ai[0].serial)
+ break;
+ w.value = ai[0].value;
+ ai[0].value = aim->value;
+ aim->value = w.value;
+ w.serial = ai[0].serial;
+ ai[0].serial = aim->serial;
+ aim->serial = w.serial;
+ }
+ }
+ }
+}
+
+void unsort(struct line *f, int l, int *b)
+{
+ register int *a;
+ register int i;
+ a = (int *) talloc((l + 1) * sizeof(int));
+ for (i = 1; i <= l; i++)
+ a[f[i].serial] = f[i].value;
+ for (i = 1; i <= l; i++)
+ b[i] = a[i];
+ free((char *) a);
+}
+
+int skipline(int f)
+{
+ register i;
+ for (i = 1; getc(input[f]) != '\n'; i++);
+ return (i);
+}
+
+void filename(char **pa1, char **pa2)
+{
+ register char *a1, *b1, *a2;
+ char buf[512];
+ struct stat stbuf;
+ int i, f;
+ a1 = *pa1;
+ a2 = *pa2;
+ if (stat(a1, &stbuf) != -1
+ && ((stbuf.st_mode & S_IFMT) == S_IFDIR)) {
+ b1 = *pa1 = malloc(100);
+ while (*b1++ = *a1++);
+ b1[-1] = '/';
+ a1 = b1;
+ while (*a1++ = *a2++)
+ if (*a2 && *a2 != '/' && a2[-1] == '/')
+ a1 = b1;
+ } else if (a1[0] == '-' && a1[1] == 0 && tempfile == 0) {
+ signal(SIGHUP, sdone);
+ signal(SIGINT, sdone);
+ signal(SIGPIPE, sdone);
+ signal(SIGTERM, sdone);
+ *pa1 = tempfile = tmpnam("diffXXXXX");
+ if ((f =
+ open(tempfile, O_CREAT | O_EXCL | O_WRONLY,
+ 0600)) < 0) {
+ mesg("cannot create ", tempfile);
+ done();
+ }
+ while ((i = read(0, buf, 512)) > 0)
+ write(f, buf, i);
+ close(f);
+ }
+}
+
+/* hashing has the effect of
+ * arranging line in 7-bit bytes and then
+ * summing 1-s complement in 16-bit hunks
+*/
+
+int readhash(FILE * f)
+{
+ long sum;
+ register unsigned shift;
+ register space;
+ register t;
+ sum = 1;
+ space = 0;
+ if (!bflag)
+ for (shift = 0; (t = getc(f)) != '\n'; shift += 7) {
+ if (t == -1)
+ return (0);
+ sum += (long) t << (shift %= HALFLONG);
+ } else
+ for (shift = 0;;) {
+ switch (t = getc(f)) {
+ case -1:
+ return (0);
+ case '\t':
+ case ' ':
+ space++;
+ continue;
+ default:
+ if (space) {
+ shift += 7;
+ space = 0;
+ }
+ sum += (long) t << (shift %= HALFLONG);
+ shift += 7;
+ continue;
+ case '\n':
+ break;
+ }
+ break;
+ }
+ sum = low(sum) + high(sum);
+ return ((short) low(sum) + (short) high(sum));
+}
+
+void prepare(int i, char *arg)
+{
+ register struct line *p;
+ register j, h;
+ if ((input[i] = fopen(arg, "r")) == NULL) {
+ mesg("cannot open ", arg);
+ done();
+ }
+ p = (struct line *) talloc(3 * sizeof(line));
+ for (j = 0; h = readhash(input[i]);) {
+ p = (struct line *) ralloc((char *) p,
+ (++j + 3) * sizeof(line));
+ p[j].value = h;
+ }
+ len[i] = j;
+ file[i] = p;
+ fclose(input[i]);
+}
+
+void prune(void)
+{
+ register i, j;
+ for (pref = 0; pref < len[0] && pref < len[1] &&
+ file[0][pref + 1].value == file[1][pref + 1].value; pref++);
+ for (suff = 0; suff < len[0] - pref && suff < len[1] - pref &&
+ file[0][len[0] - suff].value == file[1][len[1] - suff].value;
+ suff++);
+ for (j = 0; j < 2; j++) {
+ sfile[j] = file[j] + pref;
+ slen[j] = len[j] - pref - suff;
+ for (i = 0; i <= slen[j]; i++)
+ sfile[j][i].serial = i;
+ }
+}
+
+void equiv(struct line *a, int n, struct line *b, int m, int *c)
+{
+ register int i, j;
+ i = j = 1;
+ while (i <= n && j <= m) {
+ if (a[i].value < b[j].value)
+ a[i++].value = 0;
+ else if (a[i].value == b[j].value)
+ a[i++].value = j;
+ else
+ j++;
+ }
+ while (i <= n)
+ a[i++].value = 0;
+ b[m + 1].value = 0;
+ j = 0;
+ while (++j <= m) {
+ c[j] = -b[j].serial;
+ while (b[j + 1].value == b[j].value) {
+ j++;
+ c[j] = b[j].serial;
+ }
+ }
+ c[j] = -1;
+}
+
+int newcand(int x, int y, int pred)
+{
+ register struct cand *q;
+ clist =
+ (struct cand *) ralloc((char *) clist, ++clen * sizeof(cand));
+ q = clist + clen - 1;
+ q->x = x;
+ q->y = y;
+ q->pred = pred;
+ return (clen - 1);
+}
+
+int search(int *c, int k, int y)
+{
+ register int i, j, l;
+ int t;
+ if (clist[c[k]].y < y) /*quick look for typical case */
+ return (k + 1);
+ i = 0;
+ j = k + 1;
+ while ((l = (i + j) / 2) > i) {
+ t = clist[c[l]].y;
+ if (t > y)
+ j = l;
+ else if (t < y)
+ i = l;
+ else
+ return (l);
+ }
+ return (l + 1);
+}
+
+void unravel(int p)
+{
+ register int i;
+ register struct cand *q;
+ for (i = 0; i <= len[0]; i++)
+ J[i] = i <= pref ? i :
+ i > len[0] - suff ? i + len[1] - len[0] : 0;
+ for (q = clist + p; q->y != 0; q = clist + q->pred)
+ J[q->x + pref] = q->y + pref;
+}
+
+
+int stone(int *a, int n, int *b, int *c)
+{
+ register int i, k, y;
+ int j, l;
+ int oldc, tc;
+ int oldl;
+ k = 0;
+ c[0] = newcand(0, 0, 0);
+ for (i = 1; i <= n; i++) {
+ j = a[i];
+ if (j == 0)
+ continue;
+ y = -b[j];
+ oldl = 0;
+ oldc = c[0];
+ do {
+ if (y <= clist[oldc].y)
+ continue;
+ l = search(c, k, y);
+ if (l != oldl + 1)
+ oldc = c[l - 1];
+ if (l <= k) {
+ if (clist[c[l]].y <= y)
+ continue;
+ tc = c[l];
+ c[l] = newcand(i, y, oldc);
+ oldc = tc;
+ oldl = l;
+ } else {
+ c[l] = newcand(i, y, oldc);
+ k++;
+ break;
+ }
+ } while ((y = b[++j]) > 0);
+ }
+ return (k);
+}
+
+/* check does double duty:
+1. ferret out any fortuitous correspondences due
+to confounding by hashing (which result in "jackpot")
+2. collect random access indexes to the two files */
+
+void check(const char *argv[])
+{
+ register int i, j;
+ int jackpot;
+ long ctold, ctnew;
+ char c, d;
+ input[0] = fopen(argv[1], "r");
+ input[1] = fopen(argv[2], "r");
+ j = 1;
+ ixold[0] = ixnew[0] = 0;
+ jackpot = 0;
+ ctold = ctnew = 0;
+ for (i = 1; i <= len[0]; i++) {
+ if (J[i] == 0) {
+ ixold[i] = ctold += skipline(0);
+ continue;
+ }
+ while (j < J[i]) {
+ ixnew[j] = ctnew += skipline(1);
+ j++;
+ }
+ for (;;) {
+ c = getc(input[0]);
+ d = getc(input[1]);
+ ctold++;
+ ctnew++;
+ if (bflag && isspace(c) && isspace(d)) {
+ do {
+ if (c == '\n')
+ break;
+ ctold++;
+ } while (isspace(c = getc(input[0])));
+ do {
+ if (d == '\n')
+ break;
+ ctnew++;
+ } while (isspace(d = getc(input[1])));
+ }
+ if (c != d) {
+ jackpot++;
+ J[i] = 0;
+ if (c != '\n')
+ ctold += skipline(0);
+ if (d != '\n')
+ ctnew += skipline(1);
+ break;
+ }
+ if (c == '\n')
+ break;
+ }
+ ixold[i] = ctold;
+ ixnew[j] = ctnew;
+ j++;
+ }
+ for (; j <= len[1]; j++) {
+ ixnew[j] = ctnew += skipline(1);
+ }
+ fclose(input[0]);
+ fclose(input[1]);
+/*
+ if(jackpot)
+ mesg("jackpot",empty);
+*/
+}
+
+void range(int a, int b, char *separator)
+{
+ printf("%d", a > b ? b : a);
+ if (a < b) {
+ printf("%s%d", separator, b);
+ }
+}
+
+int fetch(long *f, int a, int b, FILE * lb, char *s)
+{
+ register int i, j;
+ register int nc;
+ for (i = a; i <= b; i++) {
+ fseek(lb, f[i - 1], 0);
+ nc = f[i] - f[i - 1];
+ prints(s);
+ for (j = 0; j < nc; j++)
+ putchar(getc(lb));
+ }
+}
+
+void change(int a, int b, int c, int d)
+{
+ if (a > b && c > d)
+ return;
+ anychange = 1;
+ if (opt != 1) {
+ range(a, b, ",");
+ putchar(a > b ? 'a' : c > d ? 'd' : 'c');
+ if (opt != -1)
+ range(c, d, ",");
+ } else {
+ putchar(a > b ? 'a' : c > d ? 'd' : 'c');
+ range(a, b, " ");
+ }
+ putchar('\n');
+ if (opt == 0) {
+ fetch(ixold, a, b, input[0], "< ");
+ if (a <= b && c <= d)
+ prints("---\n");
+ }
+ fetch(ixnew, c, d, input[1], opt == 0 ? "> " : empty);
+ if (opt != 0 && c <= d)
+ prints(".\n");
+}
+
+void output(const char *argv[])
+{
+ int m;
+ register int i0, i1, j1;
+ int j0;
+ input[0] = fopen(argv[1], "r");
+ input[1] = fopen(argv[2], "r");
+ m = len[0];
+ J[0] = 0;
+ J[m + 1] = len[1] + 1;
+ if (opt != -1)
+ for (i0 = 1; i0 <= m; i0 = i1 + 1) {
+ while (i0 <= m && J[i0] == J[i0 - 1] + 1)
+ i0++;
+ j0 = J[i0 - 1] + 1;
+ i1 = i0 - 1;
+ while (i1 < m && J[i1 + 1] == 0)
+ i1++;
+ j1 = J[i1 + 1] - 1;
+ J[i1] = j1;
+ change(i0, i1, j0, j1);
+ } else
+ for (i0 = m; i0 >= 1; i0 = i1 - 1) {
+ while (i0 >= 1 && J[i0] == J[i0 + 1] - 1
+ && J[i0] != 0)
+ i0--;
+ j0 = J[i0 + 1] - 1;
+ i1 = i0 + 1;
+ while (i1 > 1 && J[i1 - 1] == 0)
+ i1--;
+ j1 = J[i1 - 1] + 1;
+ J[i1] = j1;
+ change(i1, i0, j1, j0);
+ }
+ if (m == 0)
+ change(1, 0, 1, len[1]);
+}
+
+int main(int argc, const char *argv[])
+{
+ register int k;
+ const char **args;
+
+ args = argv;
+ if (argc > 3 && *argv[1] == '-') {
+ argc--;
+ argv++;
+ for (k = 1; argv[0][k]; k++) {
+ switch (argv[0][k]) {
+ case 'e':
+ opt = -1;
+ break;
+ case 'f':
+ opt = 1;
+ break;
+ case 'b':
+ bflag = 1;
+ break;
+ case 'h':
+ execv("/usr/lib/diffh", args);
+ mesg("cannot find diffh", empty);
+ done();
+ }
+ }
+ }
+ if (argc != 3) {
+ mesg("arg count", empty);
+ done();
+ }
+
+ filename(&argv[1], &argv[2]);
+ filename(&argv[2], &argv[1]);
+ prepare(0, argv[1]);
+ prepare(1, argv[2]);
+ prune();
+ sort(sfile[0], slen[0]);
+ sort(sfile[1], slen[1]);
+
+ member = (int *) file[1];
+ equiv(sfile[0], slen[0], sfile[1], slen[1], member);
+ member =
+ (int *) ralloc((char *) member, (slen[1] + 2) * sizeof(int));
+
+ class = (int *) file[0];
+ unsort(sfile[0], slen[0], class);
+ class =
+ (int *) ralloc((char *) class, (slen[0] + 2) * sizeof(int));
+
+ klist = (int *) talloc((slen[0] + 2) * sizeof(int));
+ clist = (struct cand *) talloc(sizeof(cand));
+ k = stone(class, slen[0], member, klist);
+ free((char *) member);
+ free((char *) class);
+
+ J = (int *) talloc((len[0] + 2) * sizeof(int));
+ unravel(klist[k]);
+ free((char *) clist);
+ free((char *) klist);
+
+ ixold = (long *) talloc((len[0] + 2) * sizeof(long));
+ ixnew = (long *) talloc((len[1] + 2) * sizeof(long));
+ check(argv);
+ output(argv);
+ status = anychange;
+ done();
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* diff3 - 3-way differential file comparison*/
+
+/* diff3 [-e] d13 d23 f1 f2 f3
+ *
+ * d13 = diff report on f1 vs f3
+ * d23 = diff report on f2 vs f3
+ * f1, f2, f3 the 3 files
+*/
+
+struct range {
+ int from, to;
+};
+ /* from is first in range of changed lines
+ * to is last+1
+ * from=to=line after point of insertion
+ * for added lines
+ */
+struct diff {
+ struct range old, new;
+};
+
+#define NC 200
+/* de is used to gather editing scripts,
+ * that are later spewed out in reverse order.
+ * its first element must be all zero
+ * the "new" component of de contains line positions
+ * or byte positions depending on when you look(!?)
+*/
+struct diff d13[NC];
+struct diff d23[NC];
+struct diff de[NC];
+char line[256];
+FILE *fp[3];
+int linct[3] = { 0, 0, 0 };
+
+/* the number of the last-read line in each file
+ * is kept in cline[0-2]
+*/
+int cline[3];
+/* the latest known correspondence between line
+ * numbers of the 3 files is stored in last[1-3]
+*/
+int last[4];
+int eflag;
+int debug = 0;
+
+void repos(int nchar)
+{
+ register i;
+ for (i = 0; i < 2; i++)
+ fseek(fp[i], (long) -nchar, 1);
+}
+
+void trouble(void)
+{
+ fprintf(stderr, "diff3: logic error\n");
+ abort();
+}
+
+int digit(char c)
+{
+ return (c >= '0' && c <= '9');
+}
+
+
+int number(char **lc)
+{
+ register int nn;
+ nn = 0;
+ while (digit(**lc))
+ nn = nn * 10 + *(*lc)++ - '0';
+ return (nn);
+}
+
+int getline(FILE * b)
+{
+ register i, c;
+ for (i = 0; i < sizeof(line) - 1; i++) {
+ c = getc(b);
+ if (c == EOF)
+ break;
+ line[i] = c;
+ if (c == '\n') {
+ line[++i] = 0;
+ return (i);
+ }
+ }
+ return (0);
+}
+
+int getchange(FILE * b)
+{
+ while (getline(b))
+ if (digit(line[0]))
+ return (1);
+ return (0);
+}
+
+/*pick up the line numbers of allcahnges from
+ * one change file
+ * (this puts the numbers in a vector, which is not
+ * strictly necessary, since the vector is processed
+ * in one sequential pass. The vector could be optimized
+ * out of existence)
+*/
+
+int readin(const char *name, struct diff *dd)
+{
+ register int i;
+ int a, b, c, d;
+ char kind;
+ char *p;
+ fp[0] = fopen(name, "r");
+ for (i = 0; getchange(fp[0]); i++) {
+ if (i >= NC) {
+ fprintf(stderr, "diff3: too many changes\n");
+ exit(0);
+ }
+ p = line;
+ a = b = number(&p);
+ if (*p == ',') {
+ p++;
+ b = number(&p);
+ }
+ kind = *p++;
+ c = d = number(&p);
+ if (*p == ',') {
+ p++;
+ d = number(&p);
+ }
+ if (kind == 'a')
+ a++;
+ if (kind == 'd')
+ c++;
+ b++;
+ d++;
+ dd[i].old.from = a;
+ dd[i].old.to = b;
+ dd[i].new.from = c;
+ dd[i].new.to = d;
+ }
+ dd[i].old.from = dd[i - 1].old.to;
+ dd[i].new.from = dd[i - 1].new.to;
+ fclose(fp[0]);
+ return (i);
+}
+
+
+void separate(char *s)
+{
+ printf("====%s\n", s);
+}
+
+/* print the range of line numbers, rold.from thru rold.to
+ * as n1,n2 or n1
+*/
+
+void prange(struct range *rold)
+{
+ if (rold->to <= rold->from)
+ printf("%da\n", rold->from - 1);
+ else {
+ printf("%d", rold->from);
+ if (rold->to > rold->from + 1)
+ printf(",%d", rold->to - 1);
+ printf("c\n");
+ }
+}
+
+/* skip to just befor line number from in file i
+ * if "pr" is nonzero, print all skipped stuff
+ * with string pr as a prefix
+*/
+
+int skip(int i, int from, char *pr)
+{
+ register int j, n;
+ for (n = 0; cline[i] < from - 1; n += j) {
+ if ((j = getline(fp[i])) == 0)
+ trouble();
+ if (pr)
+ printf("%s%s", pr, line);
+ cline[i]++;
+ }
+ return (n);
+}
+
+/* the range of ines rold.from thru rold.to in file i
+ * is to be changed. it is to be printed only if
+ * it does not duplicate something to be printed later
+*/
+void change(int i, struct range *rold, int dup)
+{
+ printf("%d:", i);
+ last[i] = rold->to;
+ prange(rold);
+ if (dup)
+ return;
+ if (debug)
+ return;
+ i--;
+ skip(i, rold->from, (char *) 0);
+ skip(i, rold->to, " ");
+}
+
+
+/* no difference was reported by diff between file 1(or 2)
+ * and file 3, and an artificial dummy difference (trange)
+ * must be ginned up to correspond to the change reported
+ * in the other file
+*/
+void keep(int i, struct range *rold, struct range *rnew)
+{
+ register int delta;
+ struct range trange;
+ delta = last[3] - last[i];
+ trange.from = rnew->from - delta;
+ trange.to = rnew->to - delta;
+ change(i, &trange, 1);
+}
+
+
+/* return 1 or 0 according as the old range
+ * (in file 1) contains exactly the same data
+ * as the new range (in file 2)
+*/
+
+int duplicate(struct range *r1, struct range *r2)
+{
+ register int c, d;
+ register int nchar;
+ int nline;
+ if (r1->to - r1->from != r2->to - r2->from)
+ return (0);
+ skip(0, r1->from, (char *) 0);
+ skip(1, r2->from, (char *) 0);
+ nchar = 0;
+ for (nline = 0; nline < r1->to - r1->from; nline++) {
+ do {
+ c = getc(fp[0]);
+ d = getc(fp[1]);
+ if (c == -1 || d == -1)
+ trouble();
+ nchar++;
+ if (c != d) {
+ repos(nchar);
+ return 0;
+ }
+ } while (c != '\n');
+ }
+ repos(nchar);
+ return (1);
+}
+
+/* collect an editing script for later regurgitation
+*/
+int edit(struct diff *diff, int dup, int j)
+{
+ if (((dup + 1) & eflag) == 0)
+ return (j);
+ j++;
+ de[j].old.from = diff->old.from;
+ de[j].old.to = diff->old.to;
+ de[j].new.from = de[j - 1].new.to
+ + skip(2, diff->new.from, (char *) 0);
+ de[j].new.to = de[j].new.from + skip(2, diff->new.to, (char *) 0);
+ return (j);
+}
+
+/* regurgitate */
+void edscript(int n)
+{
+ register j, k;
+ char block[512];
+ for (n = n; n > 0; n--) {
+ prange(&de[n].old);
+ fseek(fp[2], (long) de[n].new.from, 0);
+ for (k = de[n].new.to - de[n].new.from; k > 0; k -= j) {
+ j = k > 512 ? 512 : k;
+ if (fread(block, 1, j, fp[2]) != j)
+ trouble();
+ fwrite(block, 1, j, stdout);
+ }
+ printf(".\n");
+ }
+}
+
+
+void merge(int m1, int m2)
+{
+ register struct diff *d1, *d2, *d3;
+ int dup;
+ int j;
+ int t1, t2;
+ d1 = d13;
+ d2 = d23;
+ j = 0;
+ for (; (t1 = d1 < d13 + m1) | (t2 = d2 < d23 + m2);) {
+ if (debug) {
+ printf("%d,%d=%d,%d %d,%d=%d,%d\n",
+ d1->old.from, d1->old.to,
+ d1->new.from, d1->new.to,
+ d2->old.from, d2->old.to,
+ d2->new.from, d2->new.to);
+ }
+/* first file is different from others*/
+ if (!t2 || t1 && d1->new.to < d2->new.from) {
+/* stuff peculiar to 1st file */
+ if (eflag == 0) {
+ separate("1");
+ change(1, &d1->old, 0);
+ keep(2, &d1->old, &d1->new);
+ change(3, &d1->new, 0);
+ }
+ d1++;
+ continue;
+ }
+/* second file is different from others*/
+ if (!t1 || t2 && d2->new.to < d1->new.from) {
+ if (eflag == 0) {
+ separate("2");
+ keep(1, &d2->old, &d2->new);
+ change(2, &d2->old, 0);
+ change(3, &d2->new, 0);
+ }
+ d2++;
+ continue;
+ }
+/* merge overlapping changes in first file
+ * this happens after extension see below*/
+ if (d1 + 1 < d13 + m1 && d1->new.to >= d1[1].new.from) {
+ d1[1].old.from = d1->old.from;
+ d1[1].new.from = d1->new.from;
+ d1++;
+ continue;
+ }
+/* merge overlapping changes in second*/
+ if (d2 + 1 < d23 + m2 && d2->new.to >= d2[1].new.from) {
+ d2[1].old.from = d2->old.from;
+ d2[1].new.from = d2->new.from;
+ d2++;
+ continue;
+ }
+/* stuff peculiar to third file or different in all*/
+ if (d1->new.from == d2->new.from &&
+ d1->new.to == d2->new.to) {
+ dup = duplicate(&d1->old, &d2->old);
+/* dup=0 means all files differ
+ * dup =1 meands files 1&2 identical*/
+ if (eflag == 0) {
+ separate(dup ? "3" : "");
+ change(1, &d1->old, dup);
+ change(2, &d2->old, 0);
+ d3 = d1->old.to > d1->old.from ? d1 : d2;
+ change(3, &d3->new, 0);
+ } else
+ j = edit(d1, dup, j);
+ d1++;
+ d2++;
+ continue;
+ }
+/* overlapping changes from file1 & 2
+ * extend changes appropriately to
+ * make them coincide*/
+ if (d1->new.from < d2->new.from) {
+ d2->old.from -= d2->new.from - d1->new.from;
+ d2->new.from = d1->new.from;
+ } else if (d2->new.from < d1->new.from) {
+ d1->old.from -= d1->new.from - d2->new.from;
+ d1->new.from = d2->new.from;
+ }
+ if (d1->new.to > d2->new.to) {
+ d2->old.to += d1->new.to - d2->new.to;
+ d2->new.to = d1->new.to;
+ } else if (d2->new.to > d1->new.to) {
+ d1->old.to += d2->new.to - d1->new.to;
+ d1->new.to = d2->new.to;
+ }
+ }
+ if (eflag)
+ edscript(j);
+}
+
+int main(int argc, char *argv[])
+{
+ register int i, m, n;
+ if (*argv[1] == '-') {
+ switch (argv[1][1]) {
+ default:
+ eflag = 3;
+ break;
+ case '3':
+ eflag = 2;
+ break;
+ case 'x':
+ eflag = 1;
+ }
+ argv++;
+ argc--;
+ }
+ if (argc < 6) {
+ fprintf(stderr, "diff3: arg count\n");
+ exit(1);
+ }
+ m = readin(argv[1], d13);
+ n = readin(argv[2], d23);
+ for (i = 0; i <= 2; i++)
+ if ((fp[i] = fopen(argv[i + 3], "r")) == NULL) {
+ printf("diff3: can't open %s\n", argv[i + 3]);
+ exit(1);
+ }
+ merge(m, n);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define C 3
+#define RANGE 30
+#define LEN 255
+#define INF 16384
+
+char *text[2][RANGE];
+long lineno[2] = { 1, 1 }; /*no. of 1st stored line in each file */
+
+int ntext[2]; /*number of stored lines in each */
+long n0, n1; /*scan pointer in each */
+int bflag;
+int debug = 0;
+FILE *file[2];
+
+void error(const char *s, const char *t)
+{
+ fprintf(stderr, "diffh: %s%s\n", s, t);
+ exit(1);
+}
+
+void progerr(const char *s)
+{
+ error("program error ", s);
+}
+
+
+void movstr(const char *s, char *t)
+{
+ while (*t++ = *s++)
+ continue;
+}
+
+
+int range(long a, int b)
+{
+ if (b == INF)
+ printf("%ld,$", a);
+ else if (b == 0)
+ printf("%ld", a);
+ else
+ printf("%ld,%ld", a, a + b);
+}
+
+
+int change(long a, int b, long c, int d, char *s)
+{
+ range(a, b);
+ printf("%s", s);
+ range(c, d);
+ printf("\n");
+}
+
+/*stub for resychronization beyond limits of text buf*/
+int hardsynch(void)
+{
+ change(n0, INF, n1, INF, "c");
+ printf("---change record omitted\n");
+ error("can't resynchronize", "");
+ return (0);
+}
+
+ /* return pointer to line n of file f */
+char *getl(int f, long n)
+{
+ char *t;
+ int delta, nt;
+ again:
+ delta = n - lineno[f];
+ nt = ntext[f];
+ if (delta < 0)
+ progerr("1");
+ if (delta < nt)
+ return (text[f][delta]);
+ if (delta > nt)
+ progerr("2");
+ if (nt >= RANGE)
+ progerr("3");
+ if (feof(file[f]))
+ return (NULL);
+ t = text[f][nt];
+ if (t == 0) {
+ t = text[f][nt] = malloc(LEN + 1);
+ if (t == NULL)
+ if (hardsynch())
+ goto again;
+ else
+ progerr("5");
+ }
+ t = fgets(t, LEN, file[f]);
+ if (t != NULL)
+ ntext[f]++;
+ return (t);
+}
+
+ /*remove thru line n of file f from storage */
+void clrl(int f, long n)
+{
+ register int i, j;
+ j = n - lineno[f] + 1;
+ for (i = 0; i + j < ntext[f]; i++)
+ movstr(text[f][i + j], text[f][i]);
+ lineno[f] = n + 1;
+ ntext[f] -= j;
+}
+
+
+int output(int a, int b)
+{
+ register int i;
+ char *s;
+ if (a < 0)
+ change(n0 - 1, 0, n1, b, "a");
+ else if (b < 0)
+ change(n0, a, n1 - 1, 0, "d");
+ else
+ change(n0, a, n1, b, "c");
+ for (i = 0; i <= a; i++) {
+ s = getl(0, n0 + i);
+ if (s == NULL)
+ break;
+ printf("< %s", s);
+ clrl(0, n0 + i);
+ }
+ n0 += i - 1;
+ if (a >= 0 && b >= 0)
+ printf("---\n");
+ for (i = 0; i <= b; i++) {
+ s = getl(1, n1 + i);
+ if (s == NULL)
+ break;
+ printf("> %s", s);
+ clrl(1, n1 + i);
+ }
+ n1 += i - 1;
+ return (1);
+}
+
+int cmp(const char *s, const char *t)
+{
+ if (debug)
+ printf("%s:%s\n", s, t);
+ for (;;) {
+ if (bflag && isspace(*s) && isspace(*t)) {
+ while (isspace(*++s));
+ while (isspace(*++t));
+ }
+ if (*s != *t || *s == 0)
+ break;
+ s++;
+ t++;
+ }
+ return (*s - *t);
+}
+
+/* synch on C successive matches*/
+int easysynch(void)
+{
+ int i, j;
+ register k, m;
+ char *s0, *s1;
+ for (i = j = 1; i < RANGE && j < RANGE; i++, j++) {
+ s0 = getl(0, n0 + i);
+ if (s0 == NULL)
+ return (output(INF, INF));
+ for (k = C - 1; k < j; k++) {
+ for (m = 0; m < C; m++)
+ if (cmp(getl(0, n0 + i - m),
+ getl(1, n1 + k - m)) != 0)
+ goto cont1;
+ return (output(i - C, k - C));
+ cont1:;
+ }
+ s1 = getl(1, n1 + j);
+ if (s1 == NULL)
+ return (output(INF, INF));
+ for (k = C - 1; k <= i; k++) {
+ for (m = 0; m < C; m++)
+ if (cmp(getl(0, n0 + k - m),
+ getl(1, n1 + j - m)) != 0)
+ goto cont2;
+ return (output(k - C, j - C));
+ cont2:;
+ }
+ }
+ return (0);
+}
+
+FILE *dopen(const char *f1, const char *f2)
+{
+ FILE *f;
+ char b[100], *bptr;
+ const char *eptr;
+ struct stat statbuf;
+ if (cmp(f1, "-") == 0)
+ if (cmp(f2, "-") == 0)
+ error("can't do - -", "");
+ else
+ return (stdin);
+ if (stat(f1, &statbuf) == -1)
+ error("can't access ", f1);
+
+ /* FIXME: buffer length is not sanely checked, should
+ strdup and then modify the copy in situ */
+ if ((statbuf.st_mode & S_IFMT) == S_IFDIR) {
+ for (bptr = b; *bptr = *f1++; bptr++);
+ *bptr++ = '/';
+ for (eptr = f2; *eptr; eptr++)
+ if (*eptr == '/' && eptr[1] != 0 && eptr[1] != '/')
+ f2 = eptr + 1;
+ while (*bptr++ = *f2++);
+ f1 = b;
+ }
+ f = fopen(f1, "r");
+ if (f == NULL)
+ error("can't open", f1);
+ return (f);
+}
+
+
+
+int main(int argc, const char *argv[])
+{
+ char *s0, *s1;
+ if (*argv[1] == '-') {
+ argc--;
+ argv++;
+ while (*++argv[0])
+ if (*argv[0] == 'b')
+ bflag++;
+ }
+ if (argc != 3)
+ error("must have 2 file arguments", "");
+ file[0] = dopen(argv[1], argv[2]);
+ file[1] = dopen(argv[2], argv[1]);
+ for (;;) {
+ s0 = getl(0, ++n0);
+ s1 = getl(1, ++n1);
+ if (s0 == NULL || s1 == NULL)
+ break;
+ if (cmp(s0, s1) != 0) {
+ if (!easysynch() && !hardsynch())
+ progerr("5");
+ } else {
+ clrl(0, n0);
+ clrl(1, n1);
+ }
+ }
+ if (s0 == NULL && s1 == NULL)
+ return 0;
+ if (s0 == NULL)
+ output(-1, INF);
+ if (s1 == NULL)
+ output(INF, -1);
+ return 0;
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+/* join F1 F2 on stuff */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+
+#define F1 0
+#define F2 1
+#define NFLD 20 /* max field per line */
+#define comp() cmp(ppi[F1][j1],ppi[F2][j2])
+
+FILE *f[2];
+char buf[2][BUFSIZ]; /*input lines */
+char *ppi[2][NFLD]; /* pointers to fields in lines */
+char *s1,*s2;
+int j1 = 1; /* join of this field of file 1 */
+int j2 = 1; /* join of this field of file 2 */
+int olist[2*NFLD]; /* output these fields */
+int olistf[2*NFLD]; /* from these files */
+int no; /* number of entries in olist */
+int sep1 = ' '; /* default field separator */
+int sep2 = '\t';
+const char *null = "";
+int unpub1;
+int unpub2;
+int aflg;
+
+int cmp(const char *s1, const char *s2)
+{
+ return(strcmp(s1, s2));
+}
+
+int input(int n) /* get input line and split into fields */
+{
+ register int i, c;
+ char *bp;
+ char **pp;
+
+ bp = buf[n];
+ pp = ppi[n];
+ if (fgets(bp, BUFSIZ, f[n]) == NULL)
+ return(0);
+ for (i = 0; ; i++) {
+ if (sep1 == ' ') /* strip multiples */
+ while ((c = *bp) == sep1 || c == sep2)
+ bp++; /* skip blanks */
+ else
+ c = *bp;
+ if (c == '\n' || c == '\0')
+ break;
+ *pp++ = bp; /* record beginning */
+ while ((c = *bp) != sep1 && c != '\n' && c != sep2 && c != '\0')
+ bp++;
+ *bp++ = '\0'; /* mark end by overwriting blank */
+ /* fails badly if string doesn't have \n at end */
+ }
+ *pp = 0;
+ return(i);
+}
+
+int output(int on1, int on2) /* print items from olist */
+{
+ int i;
+ const char *temp;
+
+ if (no <= 0) { /* default case */
+ printf("%s", on1? ppi[F1][j1]: ppi[F2][j2]);
+ for (i = 0; i < on1; i++)
+ if (i != j1)
+ printf("%c%s", sep1, ppi[F1][i]);
+ for (i = 0; i < on2; i++)
+ if (i != j2)
+ printf("%c%s", sep1, ppi[F2][i]);
+ printf("\n");
+ } else {
+ for (i = 0; i < no; i++) {
+ temp = ppi[olistf[i]][olist[i]];
+ if(olistf[i]==F1 && on1<=olist[i] ||
+ olistf[i]==F2 && on2<=olist[i] ||
+ *temp==0)
+ temp = null;
+ printf("%s", temp);
+ if (i == no - 1)
+ printf("\n");
+ else
+ printf("%c", sep1);
+ }
+ }
+}
+
+int main(int argc, const char *argv[])
+{
+ int i;
+ int n1, n2;
+ long top2, bot2;
+
+ while (argc > 1 && argv[1][0] == '-') {
+ if (argv[1][1] == '\0')
+ break;
+ switch (argv[1][1]) {
+ case 'a':
+ switch(argv[1][2]) {
+ case '1':
+ aflg |= 1;
+ break;
+ case '2':
+ aflg |= 2;
+ break;
+ default:
+ aflg |= 3;
+ }
+ break;
+ case 'e':
+ null = argv[2];
+ argv++;
+ argc--;
+ break;
+ case 't':
+ sep1 = sep2 = argv[1][2];
+ break;
+ case 'o':
+ for (no = 0; no < 2*NFLD; no++) {
+ if (argv[2][0] == '1' && argv[2][1] == '.') {
+ olistf[no] = F1;
+ olist[no] = atoi(&argv[2][2]);
+ } else if (argv[2][0] == '2' && argv[2][1] == '.') {
+ olist[no] = atoi(&argv[2][2]);
+ olistf[no] = F2;
+ } else
+ break;
+ argc--;
+ argv++;
+ }
+ break;
+ case 'j':
+ if (argv[1][2] == '1')
+ j1 = atoi(argv[2]);
+ else if (argv[1][2] == '2')
+ j2 = atoi(argv[2]);
+ else
+ j1 = j2 = atoi(argv[2]);
+ argc--;
+ argv++;
+ break;
+ }
+ argc--;
+ argv++;
+ }
+ for (i = 0; i < no; i++)
+ olist[i]--; /* 0 origin */
+ if (argc != 3)
+ errx(1, "usage: join [-j1 x -j2 y] [-o list] file1 file2");
+ j1--;
+ j2--; /* everyone else believes in 0 origin */
+ s1 = ppi[F1][j1];
+ s2 = ppi[F2][j2];
+ if (argv[1][0] == '-')
+ f[F1] = stdin;
+ else if ((f[F1] = fopen(argv[1], "r")) == NULL)
+ errx(1, "can't open %s", argv[1]);
+ if ((f[F2] = fopen(argv[2], "r")) == NULL)
+ errx(1, "can't open %s", argv[2]);
+
+#define get1() n1=input(F1)
+#define get2() n2=input(F2)
+ get1();
+ bot2 = ftell(f[F2]);
+ get2();
+ while(n1>0 && n2>0 || aflg!=0 && n1+n2>0) {
+ if(n1>0 && n2>0 && comp()>0 || n1==0) {
+ if(aflg&2) output(0, n2);
+ bot2 = ftell(f[F2]);
+ get2();
+ } else if(n1>0 && n2>0 && comp()<0 || n2==0) {
+ if(aflg&1) output(n1, 0);
+ get1();
+ } else /*(n1>0 && n2>0 && comp()==0)*/ {
+ while(n2>0 && comp()==0) {
+ output(n1, n2);
+ top2 = ftell(f[F2]);
+ get2();
+ }
+ fseek(f[F2], bot2, 0);
+ get2();
+ get1();
+ for(;;) {
+ if(n1>0 && n2>0 && comp()==0) {
+ output(n1, n2);
+ get2();
+ } else if(n1>0 && n2>0 && comp()<0 || n2==0) {
+ fseek(f[F2], bot2, 0);
+ get2();
+ get1();
+ } else /*(n1>0 && n2>0 && comp()>0 || n1==0)*/{
+ fseek(f[F2], top2, 0);
+ bot2 = top2;
+ get2();
+ break;
+ }
+ }
+ }
+ }
+ return(0);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+FILE *dfile;
+const char *filenam = "/usr/dict/words";
+
+int fold;
+int dict;
+int tab;
+char entry[250];
+char word[250];
+char key[50];
+
+
+int compare(char *s, char *t)
+{
+ for(;*s==*t;s++,t++)
+ if(*s==0)
+ return(0);
+ return(*s==0? -1:
+ *t==0? 1:
+ *s<*t? -2:
+ 2);
+}
+
+int getword(char *w)
+{
+ register int c;
+ for(;;) {
+ c = getc(dfile);
+ if(c==EOF)
+ return(0);
+ if(c=='\n')
+ break;
+ *w++ = c;
+ }
+ *w = 0;
+ return(1);
+}
+
+int canon(const char *old, char *new)
+{
+ register int c;
+ for(;;) {
+ *new = c = *old++;
+ if(c==0||c==tab) {
+ *new = 0;
+ break;
+ }
+ if(dict) {
+ if(!isalnum(c))
+ continue;
+ }
+ if(fold) {
+ if(isupper(c))
+ *new += 'a' - 'A';
+ }
+ new++;
+ }
+}
+
+int main(int argc, const char *argv[])
+{
+ register int c;
+ long top,bot,mid;
+ while(argc>=2 && *argv[1]=='-') {
+ for(;;) {
+ switch(*++argv[1]) {
+ case 'd':
+ dict++;
+ continue;
+ case 'f':
+ fold++;
+ continue;
+ case 't':
+ tab = argv[1][1];
+ if(tab)
+ ++argv[1];
+ continue;
+ case 0:
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ argc --;
+ argv++;
+ }
+ if(argc<=1)
+ return 0;
+ if(argc==2) {
+ fold++;
+ dict++;
+ } else
+ filenam = argv[2];
+ dfile = fopen(filenam,"r");
+ if(dfile==NULL) {
+ fprintf(stderr,"look: can't open %s\n",filenam);
+ exit(2);
+ }
+ canon(argv[1],key);
+ bot = 0;
+ fseek(dfile,0L,2);
+ top = ftell(dfile);
+ for(;;) {
+ mid = (top+bot)/2;
+ fseek(dfile,mid,0);
+ do {
+ c = getc(dfile);
+ mid++;
+ } while(c!=EOF && c!='\n');
+ if(!getword(entry))
+ break;
+ canon(entry,word);
+ switch(compare(key,word)) {
+ case -2:
+ case -1:
+ case 0:
+ if(top<=mid)
+ break;
+ top = mid;
+ continue;
+ case 1:
+ case 2:
+ bot = mid;
+ continue;
+ }
+ break;
+ }
+ fseek(dfile,bot,0);
+ while(ftell(dfile)<top) {
+ if(!getword(entry))
+ return 0;
+ canon(entry,word);
+ switch(compare(key,word)) {
+ case -2:
+ return 0;
+ case -1:
+ case 0:
+ puts(entry);
+ break;
+ case 1:
+ case 2:
+ continue;
+ }
+ break;
+ }
+ while(getword(entry)) {
+ canon(entry,word);
+ switch(compare(key,word)) {
+ case -1:
+ case 0:
+ puts(entry);
+ continue;
+ }
+ break;
+ }
+ return 0;
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+
+/*
+ * You send it 10 bytes.
+ * It sends you 13 bytes.
+ * The transformation is expensive to perform
+ * (a significant part of a second).
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, const char *argv[])
+{
+ char key[8];
+ char salt[2];
+
+ read(0, key, 8);
+ read(0, salt, 2);
+ write(1, crypt(key, salt), 13);
+ return(0);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+
+/*
+ * mesg -- set current tty to accept or
+ * forbid write permission.
+ *
+ * mesg [y] [n]
+ * y allow messages
+ * n forbid messages
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+struct stat sbuf;
+
+char *tty;
+
+void newmode(int m)
+{
+ if(chmod(tty,m)<0)
+ err(1, "cannot change mode");
+}
+
+int main(int argc, char *argv[])
+{
+ int r=0;
+ tty = ttyname(2);
+ if(stat(tty, &sbuf) < 0) err(1, "cannot stat");
+ if(argc < 2) {
+ if(sbuf.st_mode & 02)
+ fprintf(stderr,"is y\n");
+ else { r=1;
+ fprintf(stderr,"is n\n");
+ }
+ } else switch(*argv[1]) {
+ case 'y':
+ newmode(0622); break;
+
+ case 'n':
+ newmode(0600); r=1; break;
+
+ default:
+ errx(-1, "usage: mesg [y] [n]");
+ }
+ exit(r);
+}
+
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied and taught about using the passwd file listed shell for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <grp.h>
+#include <pwd.h>
+
+struct group *grp;
+struct passwd *pwd;
+
+void done(const char *shell)
+{
+ register int i;
+ const char *sp = strrchr(shell, '/');
+
+ if (sp)
+ sp++;
+ else
+ sp = shell;
+
+ setuid(getuid());
+ for (i=3; i<15; i++)
+ close(i);
+ execl(shell, sp, 0);
+ printf("No shell!\n");
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ register int i;
+
+ if((pwd=getpwuid(getuid())) == NULL) {
+ printf("You do not exist!\n");
+ done("/bin/sh");
+ }
+
+ if(argc != 2) {
+ printf("usage: newgrp groupname\n");
+ done(pwd->pw_shell);
+ }
+ if((grp=getgrnam(argv[1])) == NULL) {
+ printf("%s: no such group\n", argv[1]);
+ done(pwd->pw_shell);
+ }
+ for(i=0;grp->gr_mem[i];i++)
+ if(strcmp(grp->gr_mem[i], pwd->pw_name) == 0)
+ break;
+ if(grp->gr_mem[i] == 0 && strcmp(grp->gr_name,"other")) {
+ printf("Sorry\n");
+ done(pwd->pw_shell);
+ }
+
+ if(grp->gr_passwd[0] != '\0' && pwd->pw_passwd[0] == '\0') {
+ if(strcmp(grp->gr_passwd, crypt(getpass("Password:"),grp->gr_passwd)) != 0) {
+ printf("Sorry\n");
+ done(pwd->pw_shell);
+ }
+ }
+ if(setgid(grp->gr_gid) < 0)
+ perror("setgid");
+ done(pwd->pw_shell);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+
+/*
+ * print file with headings
+ * 2+head+2+page[56]+5
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+
+int ncol = 1;
+const char *header;
+int col;
+int icol;
+FILE *file;
+char *bufp;
+#define BUFS 6720
+char buffer[BUFS]; /* for multi-column output */
+char obuf[BUFSIZ];
+#define FF 014
+int line;
+char *colp[72];
+int nofile;
+char isclosed[10];
+FILE *ifile[10];
+char **lastarg;
+int peekc;
+int fpage;
+int page;
+int colw;
+int nspace;
+int width = 72;
+int length = 66;
+int plength = 61;
+int margin = 10;
+int ntflg;
+int mflg;
+int tabc;
+char *tty;
+int mode;
+
+
+void done(void)
+{
+
+ if (tty)
+ chmod(tty, mode);
+ exit(0);
+}
+
+void onintr(int sig)
+{
+
+ if (tty)
+ chmod(tty, mode);
+ _exit(1);
+}
+
+void fixtty(void)
+{
+ struct stat sbuf;
+
+ tty = ttyname(1);
+ if (tty == 0)
+ return;
+ stat(tty, &sbuf);
+ mode = sbuf.st_mode&0777;
+ chmod(tty, 0600);
+}
+
+
+
+void nexbuf(void)
+{
+ register int n;
+ register char *rbufp;
+
+ rbufp = bufp;
+ n = &buffer[BUFS] - rbufp;
+ if (n>512)
+ n = 512;
+ if(feof(file) ||
+ (n=fread(rbufp,1,n,file)) <= 0){
+ fclose(file);
+ *rbufp = 0376;
+ }
+ else {
+ rbufp += n;
+ if (rbufp >= &buffer[BUFS])
+ rbufp = buffer;
+ *rbufp = 0375;
+ }
+ bufp = rbufp;
+}
+
+int tpgetc(int ai)
+{
+ register char **p;
+ register int c, i;
+
+ i = ai;
+ if (mflg) {
+ if((c=getc(ifile[i])) == EOF) {
+ if (isclosed[i]==0) {
+ isclosed[i] = 1;
+ if (--nofile <= 0)
+ return(0);
+ }
+ return('\n');
+ }
+ if (c==FF && ncol>0)
+ c = '\n';
+ return(c);
+ }
+loop:
+ c = **(p = &colp[i]) & 0377;
+ if (c == 0375) {
+ nexbuf();
+ c = **p & 0377;
+ }
+ if (c == 0376)
+ return(0);
+ (*p)++;
+ if (*p >= &buffer[BUFS])
+ *p = buffer;
+ if (c==0)
+ goto loop;
+ return(c);
+}
+
+pgetc(int i)
+{
+ register int c;
+
+ if (peekc) {
+ c = peekc;
+ peekc = 0;
+ } else
+ c = tpgetc(i);
+ if (tabc)
+ return(c);
+ switch (c) {
+
+ case '\t':
+ icol++;
+ if ((icol&07) != 0)
+ peekc = '\t';
+ return(' ');
+
+ case '\n':
+ icol = 0;
+ break;
+
+ case 010:
+ case 033:
+ icol--;
+ break;
+ }
+ if (c >= ' ')
+ icol++;
+ return(c);
+}
+
+void putcp(int c)
+{
+ if (page >= fpage)
+ putchar(c);
+}
+
+
+void put(int ac)
+{
+ register int ns, c;
+
+ c = ac;
+ if (tabc) {
+ putcp(c);
+ if (c=='\n')
+ line++;
+ return;
+ }
+ switch (c) {
+
+ case ' ':
+ nspace++;
+ col++;
+ return;
+
+ case '\n':
+ col = 0;
+ nspace = 0;
+ line++;
+ break;
+
+ case 010:
+ case 033:
+ if (--col<0)
+ col = 0;
+ if (--nspace<0)
+ nspace = 0;
+
+ }
+ while(nspace) {
+ if (nspace>2 && col > (ns=((col-nspace)|07))) {
+ nspace = col-ns-1;
+ putcp('\t');
+ } else {
+ nspace--;
+ putcp(' ');
+ }
+ }
+ if (c >= ' ')
+ col++;
+ putcp(c);
+}
+
+void putpage(void)
+{
+ register int lastcol, i, c;
+ int j;
+
+ if (ncol==0) {
+ while (line<plength) {
+ while((c = tpgetc(0)) && c!='\n' && c!=FF)
+ putcp(c);
+ putcp('\n');
+ line++;
+ if (c==FF)
+ break;
+ }
+ return;
+ }
+ colp[0] = colp[ncol];
+ if (mflg==0) for (i=1; i<=ncol; i++) {
+ colp[i] = colp[i-1];
+ for (j = margin; j<length; j++)
+ while((c=tpgetc(i))!='\n')
+ if (c==0)
+ break;
+ }
+ while (line<plength) {
+ lastcol = colw;
+ for (i=0; i<ncol; i++) {
+ while ((c=pgetc(i)) && c!='\n')
+ if (col<lastcol || tabc!=0)
+ put(c);
+ if (c==0)
+ continue;
+ if (tabc)
+ put(tabc);
+ else while (col<lastcol)
+ put(' ');
+ lastcol += colw;
+ }
+ while ((c = pgetc(ncol)) && c!='\n')
+ put(c);
+ put('\n');
+ }
+}
+
+void mopen(char **ap)
+{
+ register char **p, *p1;
+
+ p = ap;
+ while((p1 = *p) && p++ <= lastarg) {
+ if((ifile[nofile]=fopen(p1, "r")) == NULL){
+ isclosed[nofile] = 1;
+ nofile--;
+ }
+ else
+ isclosed[nofile] = 0;
+ if(++nofile>=10) {
+ fprintf(stderr, "pr: Too many args\n");
+ done();
+ }
+ }
+}
+
+void print(char *fp, char **argp)
+{
+ struct stat sbuf;
+ register sncol;
+ register const char *sheader;
+ register char *cbuf;
+ char linebuf[150], *cp;
+
+ if (ntflg)
+ margin = 0;
+ else
+ margin = 10;
+ if (length <= margin)
+ length = 66;
+ if (width <= 0)
+ width = 72;
+ if (ncol>72 || ncol>width) {
+ fprintf(stderr, "pr: No room for columns.\n");
+ done();
+ }
+ if (mflg) {
+ mopen(argp);
+ ncol = nofile;
+ }
+ colw = width/ncol;
+ sncol = ncol;
+ sheader = header;
+ plength = length-5;
+ if (ntflg)
+ plength = length;
+ if (--ncol<0)
+ ncol = 0;
+ if (mflg)
+ fp = 0;
+ if (fp) {
+ if((file=fopen(fp, "r"))==NULL) {
+ if (tty==NULL)
+ fprintf(stderr, "pr: can't open %s\n", fp);
+ ncol = sncol;
+ header = sheader;
+ return;
+ }
+ stat(fp, &sbuf);
+ } else {
+ file = stdin;
+ time(&sbuf.st_mtime);
+ }
+ if (header == 0)
+ header = fp?fp:"";
+ cbuf = ctime(&sbuf.st_mtime);
+ cbuf[16] = '\0';
+ cbuf[24] = '\0';
+ page = 1;
+ icol = 0;
+ colp[ncol] = bufp = buffer;
+ if (mflg==0)
+ nexbuf();
+ while (mflg&&nofile || (!mflg)&&tpgetc(ncol)>0) {
+ if (mflg==0) {
+ colp[ncol]--;
+ if (colp[ncol] < buffer)
+ colp[ncol] = &buffer[BUFS];
+ }
+ line = 0;
+ if (ntflg==0) {
+ snprintf(linebuf, 150, "\n\n%s %s %s Page %d\n\n\n",
+ cbuf+4, cbuf+20, header, page);
+ for(cp=linebuf;*cp;) put(*cp++);
+ }
+ putpage();
+ if (ntflg==0)
+ while(line<length)
+ put('\n');
+ page++;
+ }
+ fclose(file);
+ ncol = sncol;
+ header = sheader;
+}
+
+int main(int argc, char *argv[])
+{
+ int nfdone;
+
+ setbuf(stdout, obuf);
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, onintr);
+ lastarg = &argv[argc-1];
+ fixtty();
+ for (nfdone=0; argc>1; argc--) {
+ argv++;
+ if (**argv == '-') {
+ switch (*++*argv) {
+ case 'h':
+ if (argc>=2) {
+ header = *++argv;
+ argc--;
+ }
+ continue;
+
+ case 't':
+ ntflg++;
+ continue;
+
+ case 'l':
+ length = atoi(++*argv);
+ continue;
+
+ case 'w':
+ width = atoi(++*argv);
+ continue;
+
+ case 's':
+ if (*++*argv)
+ tabc = **argv;
+ else
+ tabc = '\t';
+ continue;
+
+ case 'm':
+ mflg++;
+ continue;
+
+ default:
+ ncol = atoi(*argv);
+ continue;
+ }
+ } else if (**argv == '+') {
+ fpage = atoi(++*argv);
+ } else {
+ print(*argv, argv);
+ nfdone++;
+ if (mflg)
+ break;
+ }
+ }
+ if (nfdone==0)
+ print((char *)0, (char **)0);
+ done();
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied for FUZIX */
+
+/* permuted title index
+ ptx [-t] [-i ignore] [-o only] [-w num] [-f] [input] [output]
+ Ptx reads the input file and permutes on words in it.
+ It excludes all words in the ignore file.
+ Alternately it includes words in the only file.
+ if neither is given it excludes the words in /usr/lib/eign.
+
+ The width of the output line can be changed to num
+ characters. If omitted 72 is default unless troff than 100.
+ the -f flag tells the program to fold the output
+ the -t flag says the output is for troff and the
+ output is then wider.
+
+\e make: cc ptx.c -lS
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <signal.h>
+#define DEFLTX "/usr/lib/eign"
+#define TILDE 0177
+#define SORT "/bin/sort"
+#define N 30
+#define MAX N*BUFSIZ
+#define LMAX 200
+#define MAXT 2048
+#define MASK 03777
+#define SET 1
+
+#define isabreak(c) (btable[c])
+
+int status;
+char *hasht[MAXT];
+char line[LMAX];
+char btable[128];
+int ignore;
+int only;
+int llen = 72;
+int gap = 3;
+int gutter = 3;
+int mlen = LMAX;
+int wlen;
+int rflag;
+int halflen;
+char *strtbufp, *endbufp;
+char *empty = "";
+
+const char *infile;
+FILE *inptr = stdin;
+
+const char *outfile;
+FILE *outptr = stdout;
+
+char *sortfile; /* output of sort program */
+char nofold[] = { '-', 'd', 't', TILDE, 0 };
+char fold[] = { '-', 'd', 'f', 't', TILDE, 0 };
+
+char *sortopt = nofold;
+FILE *sortptr;
+
+const char *bfile; /*contains user supplied break chars */
+FILE *bptr;
+
+
+void msg(const char *s, const char *arg)
+{
+ fprintf(stderr, "%s %s\n", s, arg);
+ return;
+}
+
+void diag(const char *s, const char *arg)
+{
+
+ msg(s, arg);
+ exit(1);
+}
+
+
+char *getline(void)
+{
+
+ register c;
+ register char *linep;
+ char *endlinep;
+
+
+ endlinep = line + mlen;
+ linep = line;
+ /* Throw away leading white space */
+
+ while (isspace(c = getc(inptr)));
+ if (c == EOF)
+ return (0);
+ ungetc(c, inptr);
+ while ((c = getc(inptr)) != EOF) {
+ switch (c) {
+
+ case '\t':
+ if (linep < endlinep)
+ *linep++ = ' ';
+ break;
+ case '\n':
+ while (isspace(*--linep));
+ *++linep = '\n';
+ return (linep);
+ default:
+ if (linep < endlinep)
+ *linep++ = c;
+ }
+ }
+ return (0);
+}
+
+void putline(char *strt, char *end)
+{
+ char *cp;
+
+ for (cp = strt; cp < end; cp++)
+ putc(*cp, sortptr);
+ /* Add extra blank before TILDE to sort correctly
+ with -fd option */
+ putc(' ', sortptr);
+ putc(TILDE, sortptr);
+ for (cp = line; cp < strt; cp++)
+ putc(*cp, sortptr);
+ putc('\n', sortptr);
+}
+
+
+int cmpword(char *cpp, char *pend, char *hpp)
+{
+ char c;
+
+ while (*hpp != '\0') {
+ c = *cpp++;
+ if ((isupper(c) ? tolower(c) : c) != *hpp++)
+ return (0);
+ }
+ if (--cpp == pend)
+ return (1);
+ return (0);
+}
+
+int hash(char *strtp, char *endp)
+{
+ char *cp, c;
+ int i, j, k;
+
+ /* Return zero hash number for single letter words */
+ if ((endp - strtp) == 1)
+ return (0);
+
+ cp = strtp;
+ c = *cp++;
+ i = (isupper(c) ? tolower(c) : c);
+ c = *cp;
+ j = (isupper(c) ? tolower(c) : c);
+ i = i * j;
+ cp = --endp;
+ c = *cp--;
+ k = (isupper(c) ? tolower(c) : c);
+ c = *cp;
+ j = (isupper(c) ? tolower(c) : c);
+ j = k * j;
+
+ k = (i ^ (j >> 2)) & MASK;
+ return (k);
+}
+
+
+void cmpline(char *pend)
+{
+
+ char *pstrt, *pchar, *cp;
+ char **hp;
+ int flag;
+
+ pchar = line;
+ if (rflag)
+ while (pchar < pend && !isspace(*pchar))
+ pchar++;
+ while (pchar < pend) {
+ /* eliminate white space */
+ if (isabreak(*pchar++))
+ continue;
+ pstrt = --pchar;
+
+ flag = 1;
+ while (flag) {
+ if (isabreak(*pchar)) {
+ hp = &hasht[hash(pstrt, pchar)];
+ pchar--;
+ while (cp = *hp++) {
+ if (hp == &hasht[MAXT])
+ hp = hasht;
+ /* possible match */
+ if (cmpword(pstrt, pchar, cp)) {
+ /* exact match */
+ if (!ignore && only)
+ putline(pstrt,
+ pend);
+ flag = 0;
+ break;
+ }
+ }
+ /* no match */
+ if (flag) {
+ if (ignore || !only)
+ putline(pstrt, pend);
+ flag = 0;
+ }
+ }
+ pchar++;
+ }
+ }
+}
+
+
+char *rtrim(char *a, char *c, int d)
+{
+ char *b, *x;
+ b = c;
+ for (x = a + 1; x <= c && x - a <= d; x++)
+ if ((x == c || isspace(x[0])) && !isspace(x[-1]))
+ b = x;
+ if (b < c && !isspace(b[0]))
+ b++;
+ return (b);
+}
+
+char *ltrim(char *c, char *b, int d)
+{
+ char *a, *x;
+ a = c;
+ for (x = b - 1; x >= c && b - x <= d; x--)
+ if (!isspace(x[0]) && (x == c || isspace(x[-1])))
+ a = x;
+ if (a > c && !isspace(a[-1]))
+ a--;
+ return (a);
+}
+
+void putout(char *strt, char *end)
+{
+ char *cp;
+
+ cp = strt;
+
+ for (cp = strt; cp < end; cp++) {
+ putc(*cp, outptr);
+ }
+}
+
+void getsort(void)
+{
+ register c;
+ register char *tilde, *linep, *ref;
+ char *p1a, *p1b, *p2a, *p2b, *p3a, *p3b, *p4a, *p4b;
+ int w;
+
+ if ((sortptr = fopen(sortfile, "r")) == NULL)
+ diag("Cannot open sorted data:", sortfile);
+
+ halflen = (llen - gutter) / 2;
+ linep = line;
+ while ((c = getc(sortptr)) != EOF) {
+ switch (c) {
+
+ case TILDE:
+ tilde = linep;
+ break;
+
+ case '\n':
+ while (isspace(linep[-1]))
+ linep--;
+ ref = tilde;
+ if (rflag) {
+ while (ref < linep && !isspace(*ref))
+ ref++;
+ *ref++ = 0;
+ }
+ /* the -1 is an overly conservative test to leave
+ space for the / that signifies truncation */
+ p3b = rtrim(p3a = line, tilde, halflen - 1);
+ if (p3b - p3a > halflen - 1)
+ p3b = p3a + halflen - 1;
+ p2a = ltrim(ref, p2b = linep, halflen - 1);
+ if (p2b - p2a > halflen - 1)
+ p2a = p2b - halflen - 1;
+ p1b = rtrim(p1a =
+ p3b + (isspace(p3b[0]) != 0), tilde,
+ w = halflen - (p2b - p2a) - gap);
+ if (p1b - p1a > w)
+ p1b = p1a;
+ p4a = ltrim(ref, p4b =
+ p2a - (isspace(p2a[-1]) != 0), w =
+ halflen - (p3b - p3a) - gap);
+ if (p4b - p4a > w)
+ p4a = p4b;
+ fprintf(outptr, ".xx \"");
+ putout(p1a, p1b);
+ /* tilde-1 to account for extra space before TILDE */
+ if (p1b != (tilde - 1) && p1a != p1b)
+ fprintf(outptr, "/");
+ fprintf(outptr, "\" \"");
+ if (p4a == p4b && p2a != ref && p2a != p2b)
+ fprintf(outptr, "/");
+ putout(p2a, p2b);
+ fprintf(outptr, "\" \"");
+ putout(p3a, p3b);
+ /* ++p3b to account for extra blank after TILDE */
+ /* ++p3b to account for extra space before TILDE */
+ if (p1a == p1b && ++p3b != tilde)
+ fprintf(outptr, "/");
+ fprintf(outptr, "\" \"");
+ if (p1a == p1b && p4a != ref && p4a != p4b)
+ fprintf(outptr, "/");
+ putout(p4a, p4b);
+ if (rflag)
+ fprintf(outptr, "\" %s\n", tilde);
+ else
+ fprintf(outptr, "\"\n");
+ linep = line;
+ break;
+
+ case '"':
+ /* put double " for " */
+ *linep++ = c;
+ default:
+ *linep++ = c;
+ }
+ }
+}
+
+void onintr(int sig)
+{
+
+ if (*sortfile)
+ unlink(sortfile);
+ exit(sig ? 1 : 0);
+}
+
+int storeh(int num, char *strtp)
+{
+ int i;
+
+ for (i = num; i < MAXT; i++) {
+ if (hasht[i] == 0) {
+ hasht[i] = strtp;
+ return (0);
+ }
+ }
+ for (i = 0; i < num; i++) {
+ if (hasht[i] == 0) {
+ hasht[i] = strtp;
+ return (0);
+ }
+ }
+ return (1);
+}
+
+int main(int argc, const char *argv[])
+{
+ register int c;
+ register char *bufp;
+ pid_t pid;
+ char *pend;
+ int fd;
+
+ const char *xfile;
+ FILE *xptr;
+
+ if (signal(SIGHUP, onintr) == SIG_IGN)
+ signal(SIGHUP, SIG_IGN);
+ if (signal(SIGINT, onintr) == SIG_IGN)
+ signal(SIGINT, SIG_IGN);
+ signal(SIGPIPE, onintr);
+ signal(SIGTERM, onintr);
+
+/* argument decoding */
+
+ xfile = DEFLTX;
+ argv++;
+ while (argc > 1 && **argv == '-') {
+ switch (*++*argv) {
+
+ case 'r':
+ rflag++;
+ break;
+ case 'f':
+ sortopt = fold;
+ break;
+
+ case 'w':
+ if (argc >= 2) {
+ argc--;
+ wlen++;
+ llen = atoi(*++argv);
+ if (llen == 0)
+ diag("Wrong width:", *argv);
+ if (llen > LMAX) {
+ llen = LMAX;
+ msg("Lines truncated to 200 chars.", empty);
+ }
+ break;
+ }
+
+ case 't':
+ if (wlen == 0)
+ llen = 100;
+ break;
+ case 'g':
+ if (argc >= 2) {
+ argc--;
+ gap = gutter = atoi(*++argv);
+ }
+ break;
+
+ case 'i':
+ if (only)
+ diag("Only file already given.", empty);
+ if (argc >= 2) {
+ argc--;
+ ignore++;
+ xfile = *++argv;
+ }
+ break;
+
+ case 'o':
+ if (ignore)
+ diag("Ignore file already given", empty);
+ if (argc >= 2) {
+ only++;
+ argc--;
+ xfile = *++argv;
+ }
+ break;
+
+ case 'b':
+ if (argc >= 2) {
+ argc--;
+ bfile = *++argv;
+ }
+ break;
+
+ default:
+ msg("Illegal argument:", *argv);
+ }
+ argc--;
+ argv++;
+ }
+
+ if (argc > 3)
+ diag("Too many filenames", empty);
+ else if (argc == 3) {
+ infile = *argv++;
+ outfile = *argv;
+ if ((outptr = fopen(outfile, "w")) == NULL)
+ diag("Cannot open output file:", outfile);
+ } else if (argc == 2) {
+ infile = *argv;
+ outfile = 0;
+ }
+
+
+ /* Default breaks of blank, tab and newline */
+ btable[' '] = SET;
+ btable['\t'] = SET;
+ btable['\n'] = SET;
+ if (bfile) {
+ if ((bptr = fopen(bfile, "r")) == NULL)
+ diag("Cannot open break char file", bfile);
+
+ while ((c = getc(bptr)) != EOF)
+ btable[c] = SET;
+ }
+
+/* Allocate space for a buffer. If only or ignore file present
+ read it into buffer. Else read in default ignore file
+ and put resulting words in buffer.
+ */
+
+
+ if ((strtbufp = calloc(N, BUFSIZ)) == NULL)
+ diag("Out of memory space", empty);
+ bufp = strtbufp;
+ endbufp = strtbufp + MAX;
+
+ if ((xptr = fopen(xfile, "r")) == NULL)
+ diag("Cannot open file", xfile);
+
+ while (bufp < endbufp && (c = getc(xptr)) != EOF) {
+ if (isabreak(c)) {
+ if (storeh(hash(strtbufp, bufp), strtbufp))
+ diag("Too many words", xfile);
+ *bufp++ = '\0';
+ strtbufp = bufp;
+ } else {
+ *bufp++ = (isupper(c) ? tolower(c) : c);
+ }
+ }
+ if (bufp >= endbufp)
+ diag("Too many words in file", xfile);
+ endbufp = --bufp;
+
+ /* open output file for sorting */
+
+ sortfile = tmpnam("ptxsXXXXX");
+ fd = open(sortfile, O_CREAT | O_EXCL | O_WRONLY, 0600);
+ if (fd < 0)
+ diag("Cannot open output for sorting:", sortfile);
+ sortptr = fdopen(fd, "w");
+
+/* get a line of data and compare each word for
+ inclusion or exclusion in the sort phase
+*/
+
+ if (infile != 0 && (inptr = fopen(infile, "r")) == NULL)
+ diag("Cannot open data: ", infile);
+ while (pend = getline())
+ cmpline(pend);
+ fclose(sortptr);
+
+ switch (pid = fork()) {
+
+ case -1: /* cannot fork */
+ diag("Cannot fork", empty);
+
+ case 0: /* child */
+ execl(SORT, SORT, sortopt, "+0", "-1", "+1",
+ sortfile, "-o", sortfile, 0);
+
+ default: /* parent */
+ while (wait(&status) != pid);
+ }
+
+
+ getsort();
+ onintr(0);
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied and defloated for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+
+#define MAX 100
+
+char types[10];
+int right[MAX];
+int left[MAX];
+int rights;
+int wrongs;
+time_t stvec;
+time_t etvec;
+time_t dtvec;
+
+
+void getline(char *s)
+{
+ register char *rs;
+
+ rs = s;
+
+ while ((*rs = getchar()) == ' ');
+ while (*rs != '\n')
+ if (*rs == 0)
+ exit(0);
+ else if (rs >= &s[99]) {
+ while ((*rs = getchar()) != '\n')
+ if (*rs == '\0')
+ exit(0);
+ } else
+ *++rs = getchar();
+ while (*--rs == ' ')
+ *rs = '\n';
+}
+
+int getnum(char *s)
+{
+ int a;
+ char c;
+
+ a = 0;
+ while ((c = *s++) >= '0' && c <= '9') {
+ a = a * 10 + c - '0';
+ }
+ return (a);
+}
+
+
+int random(int range)
+{
+ return (rand() % range);
+}
+
+int skrand(int range)
+{
+ int temp;
+ temp = random(range) + random(range);
+ if (temp > range - 1)
+ temp = 2 * range - 1 - temp;
+ return (temp);
+}
+
+void score(void)
+{
+ long l;
+ time(&etvec);
+
+ printf("\n\nRights %d; Wrongs %d; Score %d%%\n", rights, wrongs,
+ (rights * 100) / (rights + wrongs));
+
+ if (rights == 0)
+ return;
+
+ l = etvec - stvec;
+
+ printf("Total time %ld seconds; %d.%2d seconds per problem\n\n\n",
+ l, l / rights, ((l * 100) / rights)%100);
+
+ sleep(3);
+ time(&dtvec);
+ stvec += dtvec - etvec;
+}
+
+void delete(int sig)
+{
+ if (rights + wrongs == 0.) {
+ printf("\n");
+ exit(0);
+ }
+ score();
+ exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+ int range, k, dif, l;
+ char line[100];
+ int ans, pans, i, j, t;
+
+ signal(SIGINT, delete);
+
+ range = 11;
+ dif = 0;
+ while (argc > 1) {
+ switch (*argv[1]) {
+ case '+':
+ case '-':
+ case 'x':
+ case '/':
+ while (types[dif] = argv[1][dif])
+ dif++;
+ break;
+
+ default:
+ range = getnum(argv[1]) + 1;
+ }
+ argv++;
+ argc--;
+ }
+ if (range > MAX) {
+ printf("Range is too large.\n");
+ exit(0);
+ }
+
+ if (dif == 0) {
+ types[0] = '+';
+ types[1] = '-';
+ dif = 2;
+ }
+
+ for (i = 0; i < range; i++) {
+ left[i] = right[i] = i;
+ }
+ time(&stvec);
+ k = stvec;
+ srand(k);
+ k = 0;
+ l = 0;
+ goto start;
+
+ loop:
+ if (++k % 20 == 0)
+ score();
+
+ start:
+ i = skrand(range);
+ j = skrand(range);
+ if (dif > 1)
+ l = random(dif);
+
+ switch (types[l]) {
+ case '+':
+ default:
+ ans = left[i] + right[j];
+ printf("%d + %d = ", left[i], right[j]);
+ break;
+
+ case '-':
+ t = left[i] + right[j];
+ ans = left[i];
+ printf("%d - %d = ", t, right[j]);
+ break;
+
+ case 'x':
+ ans = left[i] * right[j];
+ printf("%d x %d = ", left[i], right[j]);
+ break;
+
+ case '/':
+ while (right[j] == 0)
+ j = random(range);
+ t = left[i] * right[j] + random(right[j]);
+ ans = left[i];
+ printf("%d / %d = ", t, right[j]);
+ break;
+ }
+
+
+ loop1:
+ getline(line);
+ dtvec += etvec - stvec;
+ if (line[0] == '\n')
+ goto loop1;
+ pans = getnum(line);
+ if (pans == ans) {
+ printf("Right!\n");
+ rights++;
+ goto loop;
+ } else {
+ printf("What?\n");
+ wrongs++;
+ if (range >= MAX)
+ goto loop1;
+ left[range] = left[i];
+ right[range++] = right[j];
+ goto loop1;
+ }
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* ANSIfied and some PDP11isms and bugs fixed for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#define NIL (-1)
+#define MAXGMOV 10
+#define MAXIMOVES 1000
+
+char level; /*'b'=beginner, 'i'=intermediate, 'e'=expert */
+int die1;
+int die2;
+int i;
+int j;
+int l;
+int m;
+int count;
+int red[] = { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
+ 0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
+
+int white[] = { 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5,
+ 0, 0, 0, 0, 3, 0, 5, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0
+};
+
+int probability[] = { 0, 11, 12, 13, 14, 15, 16,
+ 06, 05, 04, 03, 02, 01
+};
+
+int imoves;
+int goodmoves[MAXGMOV];
+int probmoves[MAXGMOV];
+struct {
+ int pos[4], mov[4];
+} moves[MAXIMOVES];
+
+
+void getstr(char *s)
+{
+ while ((*s = getchar()) != '\n')
+ s++;
+ *s = 0;
+}
+
+int piececount(int *player, int startrow, int endrow)
+{
+ int sum;
+ sum = 0;
+ while (startrow <= endrow)
+ sum += player[startrow++];
+ return (sum);
+}
+
+int play(int *player, int *playee, int pos[])
+{
+ int k, n, die, ipos;
+ for (k = 0; k < player[0]; k++) { /*blots on player[0] must be moved first */
+ if (pos[k] == NIL)
+ break;
+ if (pos[k] != 0) {
+ printf
+ ("piece on position 0 must be moved first\n");
+ return (-1);
+ }
+ }
+ for (k = 0; (ipos = pos[k]) != NIL; k++) {
+ die = k ? die2 : die1;
+ n = 25 - ipos - die;
+ if (player[ipos] == 0)
+ goto badmove;
+ if (n > 0 && playee[n] >= 2)
+ goto badmove;
+ if (n <= 0) {
+ if (piececount(player, 0, 18) != 0)
+ goto badmove;
+ if ((ipos + die) != 25 &&
+ piececount(player, 19, 24 - die) != 0)
+ goto badmove;
+ }
+ player[ipos]--;
+ player[ipos + die]++;
+ }
+ for (k = 0; pos[k] != NIL; k++) {
+ die = k ? die2 : die1;
+ n = 25 - pos[k] - die;
+ if (n > 0 && playee[n] == 1) {
+ playee[n] = 0;
+ playee[0]++;
+ }
+ }
+ return (0);
+
+ badmove:
+ printf("Move %d is not legal.\n", ipos);
+ while (k--) {
+ die = k ? die2 : die1;
+ player[pos[k]]++;
+ player[pos[k] + die]--;
+ }
+ return (-1);
+}
+
+
+void prtmov(int k)
+{
+ int n;
+ if (k == NIL)
+ printf("no move possible\n");
+ else
+ for (n = 0; n < 4; n++) {
+ if (moves[k].pos[n] == NIL)
+ break;
+ printf(" %d, %d", 25 - moves[k].pos[n],
+ moves[k].mov[n]);
+ }
+ printf("\n");
+}
+
+void update(int *player, int *playee, int k)
+{
+ int n, t;
+ for (n = 0; n < 4; n++) {
+ if (moves[k].pos[n] == NIL)
+ break;
+ player[moves[k].pos[n]]--;
+ player[moves[k].pos[n] + moves[k].mov[n]]++;
+ t = 25 - moves[k].pos[n] - moves[k].mov[n];
+ if (t > 0 && playee[t] == 1) {
+ playee[0]++;
+ playee[t]--;
+ }
+ }
+}
+
+/*
+void prtmovs(void)
+{
+ int i1,i2;
+ printf( "possible moves are\n");
+ for(i1=0;i1<imoves;i1++){
+ printf( "\n%d",i1);
+ for(i2=0;i2<4;i2++){
+ if(moves[i1].pos[i2]==NIL)break;
+ printf( "%d, %d",moves[i1].pos[i2],moves[i1].mov[i2]);
+ }
+ }
+ printf( "\n");
+}
+*/
+
+void roll(void)
+{
+ extern int die1, die2;
+ die1 = (rand() >> 8) % 6 + 1;
+ die2 = (rand() >> 8) % 6 + 1;
+}
+
+void moverecord(int *mover)
+{
+ extern int i, j, l, m, imoves, count;
+ int t;
+ if (imoves >= MAXIMOVES)
+ goto undo;;
+ for (t = 0; t <= 3; t++)
+ moves[imoves].pos[t] = NIL;
+ switch (count) {
+ case 4:
+ moves[imoves].pos[3] = m;
+ moves[imoves].mov[3] = die1;
+ case 3:
+ moves[imoves].pos[2] = l;
+ moves[imoves].mov[2] = die1;
+ case 2:
+ moves[imoves].pos[1] = j;
+ moves[imoves].mov[1] = die2;
+ case 1:
+ moves[imoves].pos[0] = i;
+ moves[imoves].mov[0] = die1;
+ imoves++;
+ }
+ undo:
+ switch (count) {
+ case 4:
+ break;
+ case 3:
+ mover[l]++;
+ mover[l + die1]--;
+ break;
+ case 2:
+ mover[j]++;
+ mover[j + die2]--;
+ break;
+ case 1:
+ mover[i]++;
+ mover[i + die1]--;
+ }
+}
+
+void movegen(int *mover, int *movee)
+{
+ extern int i, j, l, m, count;
+ extern int die1, die2;
+ int k;
+ for (i = 0; i <= 24; i++) {
+ count = 0;
+ if (mover[i] == 0)
+ continue;
+ if ((k = 25 - i - die1) > 0 && movee[k] >= 2)
+ if (mover[0] > 0)
+ break;
+ else
+ continue;
+ if (k <= 0) {
+ if (piececount(mover, 0, 18) != 0)
+ break;
+ if ((i + die1) != 25 &&
+ piececount(mover, 19, 24 - die1) != 0)
+ break;
+ }
+ mover[i]--;
+ mover[i + die1]++;
+ count = 1;
+ for (j = 0; j <= 24; j++) {
+ if (mover[j] == 0)
+ continue;
+ if ((k = 25 - j - die2) > 0 && movee[k] >= 2)
+ if (mover[0] > 0)
+ break;
+ else
+ continue;
+ if (k <= 0) {
+ if (piececount(mover, 0, 18) != 0)
+ break;
+ if ((j + die2) != 25 &&
+ piececount(mover, 19, 24 - die2) != 0)
+ break;
+ }
+ mover[j]--;
+ mover[j + die2]++;
+ count = 2;
+ if (die1 != die2) {
+ moverecord(mover);
+ if (mover[0] > 0)
+ break;
+ else
+ continue;
+ }
+ for (l = 0; l <= 24; l++) {
+ if (mover[l] == 0)
+ continue;
+ if ((k = 25 - l - die1) > 0
+ && movee[k] >= 2)
+ if (mover[0] > 0)
+ break;
+ else
+ continue;
+ if (k <= 0) {
+ if (piececount(mover, 0, 18) != 0)
+ break;
+ if ((l + die2) != 25 &&
+ piececount(mover, 19,
+ 24 - die1) != 0)
+ break;
+ }
+ mover[l]--;
+ mover[l + die1]++;
+ count = 3;
+ for (m = 0; m <= 24; m++) {
+ if (mover[m] == 0)
+ continue;
+ if ((k = 25 - m - die1) >= 0
+ && movee[k] >= 2)
+ if (mover[0] > 0)
+ break;
+ else
+ continue;
+ if (k <= 0) {
+ if (piececount
+ (mover, 0, 18) != 0)
+ break;
+ if ((m + die2) != 25 &&
+ piececount(mover, 19,
+ 24 -
+ die1) != 0)
+ break;
+ }
+ count = 4;
+ moverecord(mover);
+ if (mover[0] > 0)
+ break;
+ }
+ if (count == 3)
+ moverecord(mover);
+ else {
+ mover[l]++;
+ mover[l + die1]--;
+ }
+ if (mover[0] > 0)
+ break;
+ }
+ if (count == 2)
+ moverecord(mover);
+ else {
+ mover[j]++;
+ mover[j + die1]--;
+ }
+ if (mover[0] > 0)
+ break;
+ }
+ if (count == 1)
+ moverecord(mover);
+ else {
+ mover[i]++;
+ mover[i + die1]--;
+ }
+ if (mover[0] > 0)
+ break;
+ }
+}
+
+int getprob(int *player, int *playee, int start, int finish)
+{ /*returns the probability (times 102) that any
+ pieces belonging to 'player' and lying between
+ his points 'start' and 'finish' will be hit
+ by a piece belonging to playee
+ */
+ int k, n, sum;
+ sum = 0;
+ for (; start <= finish; start++) {
+ if (player[start] == 1) {
+ for (k = 1; k <= 12; k++) {
+ if ((n = 25 - start - k) < 0)
+ break;
+ if (playee[n] != 0)
+ sum += probability[k];
+ }
+ }
+ }
+ return (sum);
+}
+
+int eval(int *player, int *playee, int k, int *prob)
+{
+ extern char level;
+ int newtry[31], newother[31], *r, *q, *p, n, sum, first;
+ int ii, lastwhite, lastred;
+ *prob = sum = 0;
+ r = player + 25;
+ p = newtry;
+ q = newother;
+ while (player < r) {
+ *p++ = *player++;
+ *q++ = *playee++;
+ }
+ q = newtry + 31;
+ for (p = newtry + 25; p < q;)
+ *p++ = 0; /*zero out spaces for hit pieces */
+ for (n = 0; n < 4; n++) {
+ if (moves[k].pos[n] == NIL)
+ break;
+ newtry[moves[k].pos[n]]--;
+ newtry[ii = moves[k].pos[n] + moves[k].mov[n]]++;
+ if (ii < 25 && newother[25 - ii] == 1) {
+ newother[25 - ii] = 0;
+ newother[0]++;
+ if (ii <= 15 && level == 'e')
+ sum++; /*hit if near other's home */
+ }
+ }
+ for (lastred = 0; newother[lastred] == 0; lastred++);
+ for (lastwhite = 0; newtry[lastwhite] == 0; lastwhite++);
+ lastwhite = 25 - lastwhite;
+ if (lastwhite <= 6 && lastwhite < lastred)
+ sum = 1000;
+ if (lastwhite < lastred && level == 'e' && lastwhite > 6) { /*expert's running game.
+ First priority to get all
+ pieces into white's home */
+ for (sum = 1000; lastwhite > 6; lastwhite--)
+ sum = sum - lastwhite * newtry[25 - lastwhite];
+ }
+ for (first = 0; first < 25; first++)
+ if (newother[first] != 0)
+ break; /*find other's first piece */
+ q = newtry + 25;
+ for (p = newtry + 1; p < q;)
+ if (*p++ > 1)
+ sum++; /*blocked points are good */
+ if (first > 5) { /*only stress removing pieces if homeboard
+ cannot be hit
+ */
+ q = newtry + 31;
+ p = newtry + 25;
+ for (n = 6; p < q; n--)
+ sum += *p++ * n; /*remove pieces, but just barely */
+ }
+ if (level != 'b') {
+ r = newtry + 25 - first; /*singles past this point can't be hit */
+ for (p = newtry + 7; p < r;)
+ if (*p++ == 1)
+ sum--; /*singles are bad after 1st 6 points
+ if they can be hit */
+ q = newtry + 3;
+ for (p = newtry; p < q;)
+ sum -= *p++; /*bad to be on 1st three points */
+ }
+
+ for (n = 1; n <= 4; n++)
+ *prob += n * getprob(newtry, newother, 6 * n - 5, 6 * n);
+ return (sum);
+}
+
+int strategy(int *player, int *playee)
+{
+ extern char level;
+ int k, n, nn, bestval, moveval, prob;
+ n = 0;
+ if (imoves == 0)
+ return (NIL);
+ goodmoves[0] = NIL;
+ bestval = -32000;
+ for (k = 0; k < imoves; k++) {
+ if ((moveval = eval(player, playee, k, &prob)) < bestval)
+ continue;
+ if (moveval > bestval) {
+ bestval = moveval;
+ n = 0;
+ }
+ if (n < MAXGMOV) {
+ goodmoves[n] = k;
+ probmoves[n++] = prob;
+ }
+ }
+ if (level == 'e' && n > 1) {
+ nn = n;
+ n = 0;
+ prob = 32000;
+ for (k = 0; k < nn; k++) {
+ if ((moveval = probmoves[k]) > prob)
+ continue;
+ if (moveval < prob) {
+ prob = moveval;
+ n = 0;
+ }
+ goodmoves[n] = goodmoves[k];
+ probmoves[n++] = probmoves[k];
+ }
+ }
+ return (goodmoves[(rand() >> 4) % n]);
+}
+
+int nextmove(int *player, int *playee)
+{
+ int k;
+ imoves = 0;
+ movegen(player, playee);
+ if (die1 != die2) {
+ k = die1;
+ die1 = die2;
+ die2 = k;
+ movegen(player, playee);
+ }
+ if (imoves == 0) {
+ printf("roll was %d,%d; no white move possible\n", die1,
+ die2);
+ return (NIL);
+ }
+ k = strategy(player, playee); /*select kth possible move */
+ prtmov(k);
+ update(player, playee, k);
+ return (0);
+}
+
+
+
+
+
+void instructions(void)
+{
+ printf("To play backgammon, type the numbers of the points\n");
+ printf("from which pieces are to be moved. Thus, if the\n");
+ printf("roll is '3,5', typing '2 6' will move a piece\n");
+ printf("from point 2 three spaces to point 5,\n");
+ printf("and a piece from point 6 forward to\n");
+ printf("point 11. If the moves must be made in the\n");
+ printf("opposite order, the first character typed must\n");
+ printf("be a minus ('-'). Thus, typing\n");
+ printf("'-2 6' moves the piece on point 2\n");
+ printf("by 5, and the piece on point 6 by 3.\n");
+ printf("If you want to move a single piece several times,\n");
+ printf("the sequence of points from which it is to be\n");
+ printf("moved must be typed. Thus '14 17' will move\n");
+ printf("a piece from point 14 to point 17 and thence to\n");
+ printf("to point 22.\n");
+ printf("If a double is rolled, you should type four numbers.\n");
+ printf("Red pieces that have been removed from the board by\n");
+ printf("being hit by white are on point 0 and\n");
+ printf("must be brought in before any other move can be made.\n");
+ printf("White pieces that are hit are removed to point 25.\n");
+ printf("You will not be allowed to make an illegal move, or\n");
+ printf("to make too many moves. However, if you make too\n");
+ printf("few moves, the program does not care. In particular\n");
+ printf("you may skip your turn by typing a 'new-line'\n");
+ printf("all by itself.\n\n");
+}
+
+
+void numline(int *upcol, int *downcol, int start, int fin)
+{
+ int k, n;
+ for (k = start; k <= fin; k++) {
+ if ((n = upcol[k]) != 0 || (n = downcol[25 - k]) != 0)
+ printf("%4d", n);
+ else
+ printf(" ");
+ }
+}
+
+void colorline(int *upcol, char c1, int *downcol, char c2, int start,
+ int fin)
+{
+ int k;
+ char c;
+ for (k = start; k <= fin; k++) {
+ c = ' ';
+ if (upcol[k] != 0)
+ c = c1;
+ if (downcol[25 - k] != 0)
+ c = c2;
+ printf(" %c", c);
+ }
+}
+
+
+void prtbrd(void)
+{
+ int k;
+ printf("White's Home\n");
+ for (k = 1; k <= 6; k++)
+ printf("%4d", k);
+ printf(" ");
+ for (k = 7; k <= 12; k++)
+ printf("%4d", k);
+ putchar('\r');
+ for (k = 1; k <= 54; k++)
+ putchar('_');
+ putchar('\n');
+ numline(red, white, 1, 6);
+ printf(" ");
+ numline(red, white, 7, 12);
+ putchar('\n');
+ colorline(red, 'R', white, 'W', 1, 6);
+ printf(" ");
+ colorline(red, 'R', white, 'W', 7, 12);
+ putchar('\n');
+ if (white[0] != 0)
+ printf("%28dW\n", white[0]);
+ else
+ putchar('\n');
+ if (red[0] != 0)
+ printf("%28dR\n", red[0]);
+ else
+ putchar('\n');
+ colorline(white, 'W', red, 'R', 1, 6);
+ printf(" ");
+ colorline(white, 'W', red, 'R', 7, 12);
+ putchar('\n');
+ numline(white, red, 1, 6);
+ printf(" ");
+ numline(white, red, 7, 12);
+ putchar('\r');
+ for (k = 1; k <= 54; k++)
+ putchar('_');
+ putchar('\n');
+ for (k = 24; k >= 19; k--)
+ printf("%4d", k);
+ printf(" ");
+ for (k = 18; k >= 13; k--)
+ printf("%4d", k);
+ printf("\nRed's Home\n\n\n\n\n");
+}
+
+
+int main(int argc, char *argv[])
+{
+ int t, k, n, go[6];
+ char s[100];
+ go[5] = NIL;
+ printf("Do you want instructions? Type 'y' for yes,\n");
+ printf("anything else means no.?? ");
+ getstr(s);
+ if (*s == 'y')
+ instructions();
+
+ /* Set the randomness depending upon the user keyboard time */
+
+ srand(((uint16_t) time(NULL)) ^ getpid());
+ printf("Choose the level of your oppponent.\n");
+ printf("Type 'b' for beginner, or 'i' for intermediate.\n");
+ printf("Anything else gets you an expert.?? ");
+ level = 'e';
+ getstr(s);
+ if (*s == 'b')
+ level = 'b';
+ else if (*s == 'i')
+ level = 'i';
+ printf("You will play red. Do you wan't to move first?\n");
+ printf("Type 'y' for yes, anything else means no.?? ");
+ getstr(s);
+ if (*s == 'y')
+ goto nowhmove;
+ whitesmv:
+ roll();
+ printf("white rolls %d,%d\n", die1, die2);
+ printf("white's move is:");
+ if (nextmove(white, red) == NIL)
+ goto nowhmove;
+ if (piececount(white, 0, 24) == 0) {
+ printf("White wins\n");
+ printf
+ ("Aren't you ashamed. You've been beaten by a computer.\n");
+ exit(0);
+ }
+ nowhmove:
+ prtbrd();
+
+ roll();
+ retry:
+ printf("your roll is %d, %d\n", die1, die2);
+ printf("your move, please?? ");
+ getstr(s);
+ if (*s == 0) {
+ printf("red's move skipped\n");
+ goto whitesmv;
+ }
+ n = sscanf(s, "%d%d%d%d%d", &go[0], &go[1], &go[2], &go[3],
+ &go[4]);
+ if ((die1 != die2 && n > 2) || n > 4) {
+ printf("you've made too many moves\n");
+ goto retry;
+ }
+ go[n] = NIL;
+ if (*s == '-') {
+ go[0] = -go[0];
+ t = die1;
+ die1 = die2;
+ die2 = t;
+ }
+ for (k = 0; k < n; k++) {
+ if (0 <= go[k] && go[k] <= 24)
+ continue;
+ else {
+ printf("move %d is illegal\n", go[k]);
+ goto retry;
+ }
+ }
+ if (play(red, white, go))
+ goto retry;
+ if (piececount(red, 0, 24) == 0) {
+ printf("Red wins.\n");
+ printf
+ ("Congratulations! You have just defeated a dumb machine.\n");
+ exit(0);
+ }
+ goto whitesmv;
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+/* Re-ordered, some bugs fixed and ANSIfied for FUZIX */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Through, `my' refers to the program, `your' to the player */
+
+#define CTYPE 13
+#define CTSIZ (CTYPE+1)
+#define DECK 52
+#define NOMORE 0
+#define DOUBTIT (-1);
+
+typedef char HAND[CTSIZ];
+
+/* data structures */
+
+short debug;
+
+HAND myhand;
+HAND yourhand;
+char deck[DECK];
+short nextcd;
+int proflag;
+
+/* utility and output programs */
+
+
+void error(char *s)
+{
+ fprintf(stderr, "error: ");
+ fprintf(stderr, s);
+ exit(1);
+}
+
+int choose(char a[], int n)
+{
+ /* pick and return one at random from the n choices in a */
+ /* The last one is moved to replace the one chosen */
+ register j, t;
+
+ if (n <= 0)
+ error("null choice");
+
+ j = rand() % n;
+ t = a[j];
+ a[j] = a[n - 1];
+ return (t);
+}
+
+
+void shuffle(void)
+{
+ /* shuffle the deck, and reset nextcd */
+ /* uses the random number generator `rand' in the C library */
+ /* assumes that `srand' has already been called */
+
+ register i;
+
+ for (i = 0; i < DECK; ++i)
+ deck[i] = (i % 13) + 1; /* seed the deck */
+
+ for (i = DECK; i > 0; --i) { /* select the next card at random */
+ deck[i - 1] = choose(deck, i);
+ }
+
+ nextcd = 0;
+}
+
+int draw(void)
+{
+ if (nextcd >= DECK)
+ return (NOMORE);
+ return (deck[nextcd++]);
+}
+
+int empty(HAND h)
+{
+ register i;
+
+ for (i = 1; i <= CTYPE; ++i) {
+ if (h[i] != 0 && h[i] != 4)
+ return (0);
+ }
+ return (i);
+}
+
+int mark(HAND hand, int cd)
+{
+ if (cd != NOMORE) {
+ ++hand[cd];
+ if (hand[cd] > 4) {
+ error("mark overflow");
+ }
+ }
+ return (cd);
+}
+
+void deal(HAND hand, int n)
+{
+ while (n--) {
+ if (mark(hand, draw()) == NOMORE)
+ error("deck exhausted");
+ }
+}
+
+char *cname[] = {
+ "NOMORE!!!",
+ "A",
+ "2",
+ "3",
+ "4",
+ "5",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "J",
+ "Q",
+ "K",
+};
+
+void stats(void)
+{
+ register i, ct, b;
+
+ if (proflag)
+ printf("Pro level\n");
+ b = ct = 0;
+
+ for (i = 1; i <= CTYPE; ++i) {
+ if (myhand[i] == 4)
+ ++b;
+ else
+ ct += myhand[i];
+ }
+
+ if (b) {
+ printf("My books: ");
+ for (i = 1; i <= CTYPE; ++i) {
+ if (myhand[i] == 4)
+ printf("%s ", cname[i]);
+ }
+ printf("\n");
+ }
+
+ printf("%d cards in my hand, %d in the pool\n", ct, DECK - nextcd);
+ printf("You ask me for: ");
+}
+
+void phand(HAND h)
+{
+ register i, j;
+
+ j = 0;
+
+ for (i = 1; i <= CTYPE; ++i) {
+ if (h[i] == 4) {
+ ++j;
+ continue;
+ }
+ if (h[i]) {
+ register k;
+ k = h[i];
+ while (k--)
+ printf("%s ", cname[i]);
+ }
+ }
+
+ if (j) {
+ printf("+ Books of ");
+ for (i = 1; i <= CTYPE; ++i) {
+ if (h[i] == 4)
+ printf("%s ", cname[i]);
+ }
+ }
+
+ printf("\n");
+}
+
+
+/* print instructions */
+
+const char *inst[] = {
+ "`Go Fish' is a childrens' card game.",
+ "The Object is to accumulate `books' of 4 cards",
+ "with the same face value.",
+ "The players alternate turns; each turn begins with one",
+ "player selecting a card from his hand, and asking the",
+ "other player for all cards of that face value.",
+ "If the other player has one or more cards of that face value",
+ "in his hand, he gives them to the first player, and the",
+ "first player makes another request.",
+ "Eventually, the first player asks for a card which",
+ "is not in the second player's hand: he replies `GO FISH!'",
+ "The first player then draws a card from the `pool' of",
+ "undealt cards. If this is the card he had last requested, he",
+ "draws again.",
+ "When a book is made, either through drawing or requesting,",
+ "the cards are laid down and no further action takes",
+ "place with that face value.",
+ "To play the computer, simply make guesses by typing",
+ "a, 2, 3, 4, 5, 6, 7, 8, 9, 10, j, q, or k when asked.",
+ "Hitting return gives you information about the size of",
+ "my hand and the pool, and tells you about my books.",
+ "Saying `p' as a first guess puts you into `pro' level;",
+ "The default is pretty dumb!",
+ "Good Luck!",
+ "",
+};
+
+void instruct(void)
+{
+ register char **cpp;
+
+ printf("\n");
+
+ for (cpp = inst; **cpp != '\0'; ++cpp) {
+ printf("%s\n", *cpp);
+ }
+}
+
+
+void madebook(int x)
+{
+ printf("Made a book of %s's\n", cname[x]);
+}
+
+void score(void)
+{
+ register my, your, i;
+
+ my = your = 0;
+
+ printf("The game is over.\nMy books: ");
+
+ for (i = 1; i <= CTYPE; ++i) {
+ if (myhand[i] == 4) {
+ ++my;
+ printf("%s ", cname[i]);
+ }
+ }
+
+ printf("\nYour books: ");
+
+ for (i = 1; i <= CTYPE; ++i) {
+ if (yourhand[i] == 4) {
+ ++your;
+ printf("%s ", cname[i]);
+ }
+ }
+
+ printf("\n\nI have %d, you have %d\n", my, your);
+
+ printf("\n%s win!!!\n", my > your ? "I" : "You");
+ exit(0);
+}
+
+#define G(x) { if(go) goto err; else go = x; }
+
+int guess(void)
+{
+ /* get the guess from the tty and return it... */
+ register g, go;
+
+ go = 0;
+
+ for (;;) {
+ switch (g = getchar()) {
+
+ case 'p':
+ case 'P':
+ ++proflag;
+ continue;
+
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ G(g - '0');
+ continue;
+
+ case 'a':
+ case 'A':
+ G(1);
+ continue;
+
+ case '1':
+ G(10);
+ continue;
+
+ case '0':
+ if (go != 10)
+ goto err;
+ continue;
+
+ case 'J':
+ case 'j':
+ G(11);
+ continue;
+
+ case 'Q':
+ case 'q':
+ G(12);
+ continue;
+
+ case 'K':
+ case 'k':
+ G(13);
+ continue;
+
+ case '\n':
+ if (empty(yourhand))
+ return (NOMORE);
+ if (go == 0) {
+ stats();
+ continue;
+ }
+ return (go);
+
+ case ' ':
+ case '\t':
+ continue;
+
+ default:
+ err:
+ while (g != '\n')
+ g = getchar();
+ printf("what?\n");
+ continue;
+ }
+ }
+}
+
+/* the program's strategy appears from here to the end */
+
+char try[100];
+char ntry;
+char haveguessed[CTSIZ];
+
+char hehas[CTSIZ];
+
+void start(HAND h)
+{
+ ;
+}
+
+void hedrew(int d)
+{
+ ++hehas[d];
+}
+
+void heguessed(int d)
+{
+ ++hehas[d];
+}
+
+int myguess(void)
+{
+
+ register i, lg, t;
+
+ if (empty(myhand))
+ return (NOMORE);
+
+ /* make a list of those things which i have */
+ /* leave off any which are books */
+ /* if something is found that he has, guess it! */
+
+ ntry = 0;
+ for (i = 1; i <= CTYPE; ++i) {
+ if (myhand[i] == 0 || myhand[i] == 4)
+ continue;
+ try[ntry++] = i;
+ }
+
+ if (!proflag)
+ goto random;
+
+ /* get ones he has, if any */
+
+ for (i = 0; i < ntry; ++i) {
+ if (hehas[try[i]]) {
+ i = try[i];
+ goto gotguess;
+ }
+ }
+
+ /* is there one that has never been guessed; if so, guess it */
+ lg = 101;
+ for (i = 0; i < ntry; ++i) {
+ if (haveguessed[try[i]] < lg)
+ lg = haveguessed[try[i]];
+ }
+ /* remove all those not guessed longest ago */
+
+ t = 0;
+ for (i = 0; i < ntry; ++i) {
+ if (haveguessed[try[i]] == lg)
+ try[t++] = try[i];
+ }
+ ntry = t;
+ if (t <= 0)
+ error("bad guessing loop");
+
+ random:
+ i = choose(try, ntry); /* make a random choice */
+
+ gotguess: /* do bookkeeping */
+
+ hehas[i] = 0; /* he won't anymore! */
+ for (t = 1; t <= CTYPE; ++t) {
+ if (haveguessed[t])
+ --haveguessed[t];
+ }
+ haveguessed[i] = 100; /* will have guessed it */
+ return (i);
+
+}
+
+
+/* reflect the effect of a move on the hands */
+
+int move(HAND hs, HAND ht, int g, int v)
+{
+ /* hand hs has made a guess, g, directed towards ht */
+ /* v on indicates that the guess was made by the machine */
+ register d;
+ const char *sp, *tp;
+
+ sp = tp = "I";
+ if (v)
+ tp = "You";
+ else
+ sp = "You";
+
+ if (g == NOMORE) {
+ d = draw();
+ if (d == NOMORE)
+ score();
+ else {
+
+ printf("Empty Hand\n");
+ if (!v)
+ printf("You draw %s\n", cname[d]);
+ mark(hs, d);
+ }
+ return (0);
+ }
+
+ if (!v)
+ heguessed(g);
+
+ if (hs[g] == 0) {
+ if (v)
+ error("Rotten Guess");
+ printf("You don't have any %s's\n", cname[g]);
+ return (1);
+ }
+
+ if (ht[g]) { /* successful guess */
+ printf("%s have %d %s%s\n", tp, ht[g], cname[g],
+ ht[g] > 1 ? "'s" : "");
+ hs[g] += ht[g];
+ ht[g] = 0;
+ if (hs[g] == 4)
+ madebook(g);
+ return (1);
+ }
+
+ /* GO FISH! */
+
+ printf("%s say \"GO FISH!\"\n", tp);
+
+ newdraw:
+ d = draw();
+ if (d == NOMORE) {
+ printf("No more cards\n");
+ return (0);
+ }
+ mark(hs, d);
+ if (!v)
+ printf("You draw %s\n", cname[d]);
+ if (hs[d] == 4)
+ madebook(d);
+ if (d == g) {
+ printf("%s drew the guess, so draw again\n", sp);
+ if (!v)
+ hedrew(d);
+ goto newdraw;
+ }
+ return (0);
+}
+
+void game(void)
+{
+
+ shuffle();
+
+ deal(myhand, 7);
+ deal(yourhand, 7);
+
+ start(myhand);
+
+ for (;;) {
+
+ register g;
+
+
+ /* you make repeated guesses */
+
+ for (;;) {
+ printf("your hand is: ");
+ phand(yourhand);
+ printf("you ask me for: ");
+ if (!move(yourhand, myhand, g = guess(), 0))
+ break;
+ printf("Guess again\n");
+ }
+
+ /* I make repeated guesses */
+
+ for (;;) {
+ if ((g = myguess()) != NOMORE) {
+ printf("I ask you for: %s\n", cname[g]);
+ }
+ if (!move(myhand, yourhand, g, 1))
+ break;
+ printf("I get another guess\n");
+ }
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ /* initialize shuffling, ask for instructions, play game, die */
+ register int c;
+
+ if (argc > 1 && argv[1][0] == '-') {
+ while (argv[1][0] == '-') {
+ ++argv[1];
+ ++debug;
+ }
+ argv++;
+ argc--;
+ }
+
+
+ printf("instructions?\n");
+ if ((c = getchar()) != '\n') {
+ if (c != 'n')
+ instruct();
+ while (getchar() != '\n');
+ }
+
+ srand(getpid() ^ ((uint16_t) time(NULL)));
+ game();
+}
--- /dev/null
+/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+/*
+ * wumpus
+ * stolen from PCC Vol 2 No 1
+ */
+
+#define NBAT 3
+#define NROOM 20
+#define NTUNN 3
+#define NPIT 3
+
+struct room {
+ int tunn[NTUNN];
+ int flag;
+} room[NROOM];
+
+char *intro[] = {
+ "\n",
+ "Welcome to 'Hunt the Wumpus.'\n",
+ "\n",
+ "The Wumpus lives in a cave of %d rooms.\n",
+ "Each room has %d tunnels leading to other rooms.\n",
+ "\n",
+ "Hazards:\n",
+ "\n",
+ "Bottomless Pits - Some rooms have Bottomless Pits in them.\n",
+ " If you go there, you fall into the pit and lose!\n",
+ "Super Bats - Some other rooms have super bats.\n",
+ " If you go there, a bat will grab you and take you to\n",
+ " somewhere else in the cave where you could\n",
+ " fall into a pit or run into the . . .\n",
+ "\n",
+ "Wumpus:\n",
+ "\n",
+ "The Wumpus is not bothered by the hazards since\n",
+ "he has sucker feet and is too big for a bat to lift.\n",
+ "\n",
+ "Usually he is asleep.\n",
+ "Two things wake him up:\n",
+ " your entering his room\n",
+ " your shooting an arrow anywhere in the cave.\n",
+ "If the wumpus wakes, he either decides to move one room or\n",
+ "stay where he was. But if he ends up where you are,\n",
+ "he eats you up and you lose!\n",
+ "\n",
+ "You:\n",
+ "\n",
+ "Each turn you may either move or shoot a crooked arrow.\n",
+ "\n",
+ "Moving - You can move to one of the adjoining rooms;\n",
+ " that is, to one that has a tunnel connecting it with\n",
+ " the room you are in.\n",
+ "\n",
+ "Shooting - You have 5 arrows. You lose when you run out.\n",
+ " Each arrow can go from 1 to 5 rooms.\n",
+ " You aim by telling the computer\n",
+ " The arrow's path is a list of room numbers\n",
+ " telling the arrow which room to go to next.\n",
+ " The list is terminated with a 0.\n",
+ " The first room in the path must be connected to the\n",
+ " room you are in. Each succeeding room must be\n",
+ " connected to the previous room.\n",
+ " If there is no tunnel between two of the rooms\n",
+ " in the arrow's path, the arrow chooses one of the\n",
+ " three tunnels from the room it's in and goes its\n",
+ " own way.\n",
+ "\n",
+ " If the arrow hits the wumpus, you win!\n",
+ " If the arrow hits you, you lose!\n",
+ "\n",
+ "Warnings:\n",
+ "\n",
+ "When you are one or two rooms away from the wumpus,\n",
+ "the computer says:\n",
+ " 'I smell a Wumpus'\n",
+ "When you are one room away from some other hazard, it says:\n",
+ " Bat - 'Bats nearby'\n",
+ " Pit - 'I feel a draft'\n",
+ "\n",
+ 0,
+};
+
+#define BAT 01
+#define PIT 02
+#define WUMP 04
+
+int arrow;
+int loc;
+int wloc;
+int tchar;
+
+char rline(void)
+{
+ register char c, r;
+
+ while ((c = getchar()) == ' ');
+ r = c;
+ while (c != '\n' && c != ' ') {
+ if (c == '\0')
+ exit(0);
+ c = getchar();
+ }
+ tchar = c;
+ return (r);
+}
+
+int rnum(int n)
+{
+ time_t t;
+ static int16_t first[2];
+
+ if (first[1] == 0) {
+ time(&t);
+ first[0] = (int) t;
+ first[1] = ((uint32_t) t) >> 16;
+ srand((first[1] * first[0]) ^ first[1]);
+ }
+ return ((rand() / 32768.0) * n);
+}
+
+int rin(void)
+{
+ register n, c;
+
+ n = 0;
+ c = getchar();
+ while (c != '\n' && c != ' ') {
+ if (c < '0' || c > '9') {
+ while (c != '\n') {
+ if (c == 0)
+ exit(0);
+ c = getchar();
+ }
+ return (0);
+ }
+ n = n * 10 + c - '0';
+ c = getchar();
+ }
+ return (n);
+}
+
+int near(struct room *ap, int ahaz)
+{
+ register struct room *p;
+ register haz, i;
+
+ p = ap;
+ haz = ahaz;
+ for (i = 0; i < NTUNN; i++)
+ if (room[p->tunn[i]].flag & haz)
+ return (1);
+ return (0);
+}
+
+int icomp(const void *v1, const void *v2)
+{
+ const int *p1 = v1;
+ const int *p2 = v2;
+
+ return (*p1 - *p2);
+}
+
+int tunnel(int i)
+{
+ register struct room *p;
+ register n, j;
+ int c;
+
+ c = 20;
+
+ loop:
+ n = rnum(NROOM);
+ if (n == i)
+ if (--c > 0)
+ goto loop;
+ p = &room[n];
+ for (j = 0; j < NTUNN; j++)
+ if (p->tunn[j] == -1) {
+ p->tunn[j] = i;
+ return (n);
+ }
+ goto loop;
+}
+
+
+int main(int argc, char *argv[])
+{
+ register int i, j;
+ register struct room *p;
+ int k;
+
+ printf("Instructions? (y-n) ");
+ if (rline() == 'y')
+ for (i = 0; intro[i]; i++)
+ printf(intro[i], i & 1 ? NROOM : NTUNN);
+
+
+/*
+ * initialize the room connections
+ */
+
+ init:
+ p = &room[0];
+ for (i = 0; i < NROOM; i++) {
+ for (j = 0; j < NTUNN; j++)
+ p->tunn[j] = -1;
+ p++;
+ }
+ k = 0;
+ for (i = 1; i < NROOM;) {
+ j = rnum(NROOM);
+ p = &room[j];
+ if (j == k || p->tunn[0] >= 0 || p->tunn[1] >= 0)
+ continue;
+ p->tunn[1] = k;
+ room[k].tunn[0] = j;
+ k = j;
+ i++;
+ }
+ p = &room[0];
+ for (i = 0; i < NROOM; i++) {
+ for (j = 0; j < NTUNN; j++) {
+ if (p->tunn[j] < 0)
+ p->tunn[j] = tunnel(i);
+ if (p->tunn[j] == i)
+ goto init;
+ for (k = 0; k < j; k++)
+ if (p->tunn[j] == p->tunn[k])
+ goto init;
+ }
+ qsort(&p->tunn[0], NTUNN, 2, icomp);
+ p++;
+ }
+
+/*
+ * put in player, wumpus,
+ * pits and bats
+ */
+
+ setup:
+ arrow = 5;
+ p = &room[0];
+ for (i = 0; i < NROOM; i++) {
+ p->flag = 0;
+ p++;
+ }
+ for (i = 0; i < NPIT;) {
+ p = &room[rnum(NROOM)];
+ if ((p->flag & PIT) == 0) {
+ p->flag |= PIT;
+ i++;
+ }
+ }
+ for (i = 0; i < NBAT;) {
+ p = &room[rnum(NROOM)];
+ if ((p->flag & (PIT | BAT)) == 0) {
+ p->flag |= BAT;
+ i++;
+ }
+ }
+ i = rnum(NROOM);
+ wloc = i;
+ room[i].flag |= WUMP;
+ for (;;) {
+ i = rnum(NROOM);
+ if ((room[i].flag & (PIT | BAT | WUMP)) == 0) {
+ loc = i;
+ break;
+ }
+ }
+
+/*
+ * main loop of the game
+ */
+
+ loop:
+ printf("You are in room %d\n", loc + 1);
+ p = &room[loc];
+ if (p->flag & PIT) {
+ printf("You fell into a pit\n");
+ goto done;
+ }
+ if (p->flag & WUMP) {
+ printf("You were eaten by the wumpus\n");
+ goto done;
+ }
+ if (p->flag & BAT) {
+ printf("Theres a bat in your room\n");
+ loc = rnum(NROOM);
+ goto loop;
+ }
+ for (i = 0; i < NTUNN; i++)
+ if (near(&room[p->tunn[i]], WUMP))
+ goto nearwump;
+ if (near(p, WUMP)) {
+ nearwump:
+ printf("I smell a wumpus\n");
+ }
+ if (near(p, BAT))
+ printf("Bats nearby\n");
+ if (near(p, PIT))
+ printf("I feel a draft\n");
+ printf("There are tunnels to");
+ for (i = 0; i < NTUNN; i++)
+ printf(" %d", p->tunn[i] + 1);
+ printf("\n");
+
+ again:
+ printf("Move or shoot (m-s) ");
+ switch (rline()) {
+ case 'm':
+ if (tchar == '\n')
+ printf("which room? ");
+ i = rin() - 1;
+ for (j = 0; j < NTUNN; j++)
+ if (i == p->tunn[j])
+ goto groom;
+ printf("You hit the wall\n");
+ goto again;
+ groom:
+ loc = i;
+ if (i == wloc)
+ goto mwump;
+ goto loop;
+
+ case 's':
+ if (tchar == '\n')
+ printf("Give list of rooms terminated by 0\n");
+ for (i = 0; i < 5; i++) {
+ j = rin() - 1;
+ if (j == -1)
+ break;
+ ranarw:
+ for (k = 0; k < NTUNN; k++)
+ if (j == p->tunn[k])
+ goto garow;
+ j = rnum(NROOM);
+ goto ranarw;
+ garow:
+ p = &room[j];
+ if (j == loc) {
+ printf("You shot yourself\n");
+ goto done;
+ }
+ if (p->flag & WUMP) {
+ printf("You slew the wumpus\n");
+ goto done;
+ }
+ }
+ if (--arrow == 0) {
+ printf("That was your last shot\n");
+ goto done;
+ }
+ goto mwump;
+ }
+
+ goto again;
+
+ mwump:
+ p = &room[wloc];
+ p->flag &= ~WUMP;
+ i = rnum(NTUNN + 1);
+ if (i != NTUNN)
+ wloc = p->tunn[i];
+ room[wloc].flag |= WUMP;
+ goto loop;
+
+ done:
+ printf("Another game? (y-n) ");
+ if (rline() == 'y') {
+ printf("Same room setup? (y-n) ");
+ if (rline() == 'y')
+ goto setup;
+ goto init;
+ }
+}