From 45195f6b2848dd513441676df2108551fd85c6f6 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 18 Mar 2015 22:52:18 +0000 Subject: [PATCH] Applications/V7: Add the first batch of ANSIfied V7 apps Also add the need BSD style copyright on them --- Applications/V7/COPYRIGHT | 146 ++ Applications/V7/cmd/ac.c | 263 ++++ Applications/V7/cmd/accton.c | 19 + Applications/V7/cmd/at.c | 303 ++++ Applications/V7/cmd/atrun.c | 113 ++ Applications/V7/cmd/col.c | 316 ++++ Applications/V7/cmd/comm.c | 177 +++ Applications/V7/cmd/cron.c | 252 ++++ Applications/V7/cmd/crypt.c | 97 ++ Applications/V7/cmd/dc.c | 2191 ++++++++++++++++++++++++++++ Applications/V7/cmd/dd.c | 551 +++++++ Applications/V7/cmd/deroff.c | 466 ++++++ Applications/V7/cmd/diff.c | 645 ++++++++ Applications/V7/cmd/diff3.c | 421 ++++++ Applications/V7/cmd/diffh.c | 265 ++++ Applications/V7/cmd/join.c | 209 +++ Applications/V7/cmd/look.c | 164 +++ Applications/V7/cmd/makekey.c | 23 + Applications/V7/cmd/mesg.c | 52 + Applications/V7/cmd/newgrp.c | 66 + Applications/V7/cmd/pr.c | 425 ++++++ Applications/V7/cmd/ptx.c | 547 +++++++ Applications/V7/games/arithmetic.c | 204 +++ Applications/V7/games/backgammon.c | 670 +++++++++ Applications/V7/games/fish.c | 566 +++++++ Applications/V7/games/wump.c | 381 +++++ 26 files changed, 9532 insertions(+) create mode 100644 Applications/V7/COPYRIGHT create mode 100644 Applications/V7/cmd/ac.c create mode 100644 Applications/V7/cmd/accton.c create mode 100644 Applications/V7/cmd/at.c create mode 100644 Applications/V7/cmd/atrun.c create mode 100644 Applications/V7/cmd/col.c create mode 100644 Applications/V7/cmd/comm.c create mode 100644 Applications/V7/cmd/cron.c create mode 100644 Applications/V7/cmd/crypt.c create mode 100644 Applications/V7/cmd/dc.c create mode 100644 Applications/V7/cmd/dd.c create mode 100644 Applications/V7/cmd/deroff.c create mode 100644 Applications/V7/cmd/diff.c create mode 100644 Applications/V7/cmd/diff3.c create mode 100644 Applications/V7/cmd/diffh.c create mode 100644 Applications/V7/cmd/join.c create mode 100644 Applications/V7/cmd/look.c create mode 100644 Applications/V7/cmd/makekey.c create mode 100644 Applications/V7/cmd/mesg.c create mode 100644 Applications/V7/cmd/newgrp.c create mode 100644 Applications/V7/cmd/pr.c create mode 100644 Applications/V7/cmd/ptx.c create mode 100644 Applications/V7/games/arithmetic.c create mode 100644 Applications/V7/games/backgammon.c create mode 100644 Applications/V7/games/fish.c create mode 100644 Applications/V7/games/wump.c diff --git a/Applications/V7/COPYRIGHT b/Applications/V7/COPYRIGHT new file mode 100644 index 00000000..8bc1f983 --- /dev/null +++ b/Applications/V7/COPYRIGHT @@ -0,0 +1,146 @@ +[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. diff --git a/Applications/V7/cmd/ac.c b/Applications/V7/cmd/ac.c new file mode 100644 index 00000000..0cfb5350 --- /dev/null +++ b/Applications/V7/cmd/ac.c @@ -0,0 +1,263 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied and defloated for FUZIX */ + +/* + * acct [ -w wtmp ] [ -d ] [ -p ] [ people ] + */ + +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/Applications/V7/cmd/accton.c b/Applications/V7/cmd/accton.c new file mode 100644 index 00000000..34af3ea9 --- /dev/null +++ b/Applications/V7/cmd/accton.c @@ -0,0 +1,19 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied for FUZIX */ + +#include +#include +#include + +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); +} diff --git a/Applications/V7/cmd/at.c b/Applications/V7/cmd/at.c new file mode 100644 index 00000000..0128c151 --- /dev/null +++ b/Applications/V7/cmd/at.c @@ -0,0 +1,303 @@ +/* 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 +#include +#include +#include +#include +#include +#include + +#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); +} diff --git a/Applications/V7/cmd/atrun.c b/Applications/V7/cmd/atrun.c new file mode 100644 index 00000000..bab11707 --- /dev/null +++ b/Applications/V7/cmd/atrun.c @@ -0,0 +1,113 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +/* + * Run programs submitted by at. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +# 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); +} diff --git a/Applications/V7/cmd/col.c b/Applications/V7/cmd/col.c new file mode 100644 index 00000000..14d144a1 --- /dev/null +++ b/Applications/V7/cmd/col.c @@ -0,0 +1,316 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfield for FUZIX */ + +#include +#include +#include +#include + +#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; +} diff --git a/Applications/V7/cmd/comm.c b/Applications/V7/cmd/comm.c new file mode 100644 index 00000000..cfa161ef --- /dev/null +++ b/Applications/V7/cmd/comm.c @@ -0,0 +1,177 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied for FUZIX */ + +#include +#include +#include +#include + +#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; + } + } +} diff --git a/Applications/V7/cmd/cron.c b/Applications/V7/cmd/cron.c new file mode 100644 index 00000000..a46859e7 --- /dev/null +++ b/Applications/V7/cmd/cron.c @@ -0,0 +1,252 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied for FUZIX */ + +/* FIXME: hardcoded UID 1 assumption */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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); + } + } +} diff --git a/Applications/V7/cmd/crypt.c b/Applications/V7/cmd/crypt.c new file mode 100644 index 00000000..e822bdee --- /dev/null +++ b/Applications/V7/cmd/crypt.c @@ -0,0 +1,97 @@ +/* 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 +#include +#include +#include + +#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>= 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=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; + } + } +} diff --git a/Applications/V7/cmd/dc.c b/Applications/V7/cmd/dc.c new file mode 100644 index 00000000..ba86a5c4 --- /dev/null +++ b/Applications/V7/cmd/dc.c @@ -0,0 +1,2191 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfield for FUZIX */ + +#include +#include +#include +#include +#include + +#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); +} diff --git a/Applications/V7/cmd/dd.c b/Applications/V7/cmd/dd.c new file mode 100644 index 00000000..ebb5addd --- /dev/null +++ b/Applications/V7/cmd/dd.c @@ -0,0 +1,551 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied for FUZIX */ + +#include +#include +#include +#include + +#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; cibuf;) + *--ip = 0; + ibc = read(ibf, ibuf, ibs); + } + if(ibc == -1) { + perror("read"); + if((cflag&NERR) == 0) { + flsh(); + term(); + } + ibc = 0; + for(c=0; c>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; +} diff --git a/Applications/V7/cmd/deroff.c b/Applications/V7/cmd/deroff.c new file mode 100644 index 00000000..cb6e56da --- /dev/null +++ b/Applications/V7/cmd/deroff.c @@ -0,0 +1,466 @@ +/* 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 +#include +#include +#include + +/* 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(); +} diff --git a/Applications/V7/cmd/diff.c b/Applications/V7/cmd/diff.c new file mode 100644 index 00000000..d1e890b5 --- /dev/null +++ b/Applications/V7/cmd/diff.c @@ -0,0 +1,645 @@ +/* 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_____). In particular, this +* collects the equivalence classes in file1 together. +* Subroutine equiv____ 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_____ squeezes file1 into a single +* array member______ 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______ are unsorted_______ into +* array class_____ according to the original order of file0. +* +* The cleverness lies in routine stone______. This marches +* through the lines of file0, developing a vector klist_____ +* 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____) 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_______. +* +* With J in hand, the matches there recorded are +* check_____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 +#include +#include +#include +#include +#include +#include +#include +#include +#define prints(s) fputs(s,stdout) + +#define HALFLONG 16 +#define low(x) (x&((1L<>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(); +} diff --git a/Applications/V7/cmd/diff3.c b/Applications/V7/cmd/diff3.c new file mode 100644 index 00000000..44d8a037 --- /dev/null +++ b/Applications/V7/cmd/diff3.c @@ -0,0 +1,421 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied for FUZIX */ + +#include +#include +#include +#include + +/* 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); +} diff --git a/Applications/V7/cmd/diffh.c b/Applications/V7/cmd/diffh.c new file mode 100644 index 00000000..68a375a6 --- /dev/null +++ b/Applications/V7/cmd/diffh.c @@ -0,0 +1,265 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied for FUZIX */ + +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/Applications/V7/cmd/join.c b/Applications/V7/cmd/join.c new file mode 100644 index 00000000..d89bfefd --- /dev/null +++ b/Applications/V7/cmd/join.c @@ -0,0 +1,209 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied for FUZIX */ + +/* join F1 F2 on stuff */ + +#include +#include +#include +#include +#include + +#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); +} diff --git a/Applications/V7/cmd/look.c b/Applications/V7/cmd/look.c new file mode 100644 index 00000000..90531888 --- /dev/null +++ b/Applications/V7/cmd/look.c @@ -0,0 +1,164 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied for FUZIX */ + +#include +#include +#include + +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) +#include +#include + +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); +} diff --git a/Applications/V7/cmd/mesg.c b/Applications/V7/cmd/mesg.c new file mode 100644 index 00000000..be6d1102 --- /dev/null +++ b/Applications/V7/cmd/mesg.c @@ -0,0 +1,52 @@ +/* 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 +#include +#include +#include +#include +#include + +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); +} + diff --git a/Applications/V7/cmd/newgrp.c b/Applications/V7/cmd/newgrp.c new file mode 100644 index 00000000..39cbd8c7 --- /dev/null +++ b/Applications/V7/cmd/newgrp.c @@ -0,0 +1,66 @@ +/* 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 +#include +#include +#include +#include +#include + +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); +} diff --git a/Applications/V7/cmd/pr.c b/Applications/V7/cmd/pr.c new file mode 100644 index 00000000..6d500e85 --- /dev/null +++ b/Applications/V7/cmd/pr.c @@ -0,0 +1,425 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +/* + * print file with headings + * 2+head+2+page[56]+5 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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=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(line1; 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(); +} diff --git a/Applications/V7/cmd/ptx.c b/Applications/V7/cmd/ptx.c new file mode 100644 index 00000000..ed28aa5d --- /dev/null +++ b/Applications/V7/cmd/ptx.c @@ -0,0 +1,547 @@ +/* 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. + + make: cc ptx.c -lS + */ + +#include +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/Applications/V7/games/arithmetic.c b/Applications/V7/games/arithmetic.c new file mode 100644 index 00000000..6d49b7ea --- /dev/null +++ b/Applications/V7/games/arithmetic.c @@ -0,0 +1,204 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied and defloated for FUZIX */ + +#include +#include +#include +#include +#include + +#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; + } +} diff --git a/Applications/V7/games/backgammon.c b/Applications/V7/games/backgammon.c new file mode 100644 index 00000000..8cd11226 --- /dev/null +++ b/Applications/V7/games/backgammon.c @@ -0,0 +1,670 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* ANSIfied and some PDP11isms and bugs fixed for FUZIX */ + +#include +#include +#include +#include + +#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> 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; +} diff --git a/Applications/V7/games/fish.c b/Applications/V7/games/fish.c new file mode 100644 index 00000000..5d2d607d --- /dev/null +++ b/Applications/V7/games/fish.c @@ -0,0 +1,566 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ +/* Re-ordered, some bugs fixed and ANSIfied for FUZIX */ + +#include +#include +#include + +/* 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(); +} diff --git a/Applications/V7/games/wump.c b/Applications/V7/games/wump.c new file mode 100644 index 00000000..8ab384f8 --- /dev/null +++ b/Applications/V7/games/wump.c @@ -0,0 +1,381 @@ +/* UNIX V7 source code: see /COPYRIGHT or www.tuhs.org for details. */ + +#include +#include + + +/* + * 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; + } +} -- 2.34.1