summaryrefslogtreecommitdiff
path: root/systems/knuth/local/mf-sparc
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /systems/knuth/local/mf-sparc
Initial commit
Diffstat (limited to 'systems/knuth/local/mf-sparc')
-rw-r--r--systems/knuth/local/mf-sparc/Makefile73
-rw-r--r--systems/knuth/local/mf-sparc/ext.c457
-rw-r--r--systems/knuth/local/mf-sparc/ext.h38
-rw-r--r--systems/knuth/local/mf-sparc/gftype.in2
-rw-r--r--systems/knuth/local/mf-sparc/ini_to_trap38
-rw-r--r--systems/knuth/local/mf-sparc/inimf.ch1505
-rw-r--r--systems/knuth/local/mf-sparc/mf.pool824
-rw-r--r--systems/knuth/local/mf-sparc/mf_arith.c142
-rw-r--r--systems/knuth/local/mf-sparc/mf_sunwin.c90
-rw-r--r--systems/knuth/local/mf-sparc/mf_window.h15
-rw-r--r--systems/knuth/local/mf-sparc/plain.basebin0 -> 56640 bytes
-rw-r--r--systems/knuth/local/mf-sparc/plain.log16
-rw-r--r--systems/knuth/local/mf-sparc/trap1.in3
-rw-r--r--systems/knuth/local/mf-sparc/trap2.in1
14 files changed, 3204 insertions, 0 deletions
diff --git a/systems/knuth/local/mf-sparc/Makefile b/systems/knuth/local/mf-sparc/Makefile
new file mode 100644
index 0000000000..2bdb6536d4
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/Makefile
@@ -0,0 +1,73 @@
+# Make executable files for this workstation, using the master TeX sources
+
+PFLAGS= -I..
+CFLAGS= -g -I.. -I/usr/openwin/include
+#CFLAGS= -O -I.. -I/usr/openwin/include
+#LIBS= -lsuntool -lsunwindow -lpixrect
+LIBS= -L/usr/openwin/lib -lxview -lolgx -lX11
+
+PC= time pc
+
+all: inimf
+
+traptest: trapmf
+ -trapmf < trap1.in
+ mv trap.log trapin.log
+ -trapmf < trap2.in | tee trap.fot
+ gftype trap.72270gf trap.typ < gftype.in
+ tftopl trap.tfm trap.pl
+ rm -f *.dif
+ -diff trapin.log ../../dist/mf/trapin.log > trapin.log.dif
+ -diff trap.log ../../dist/mf/trap.log > trap.log.dif
+ -diff trap.fot ../../dist/mf/trap.fot > trap.fot.dif
+ -diff trap.typ ../../dist/mf/trap.typ > trap.typ.dif
+ -diff trap.pl ../../dist/mf/trap.pl > trap.pl.dif
+ more trapin.log.dif trap.log.dif trap.typ.dif trap.fot.dif trap.pl.dif
+
+%.p: %.ch
+ tangle ../../dist/mf/mf.web $*.ch
+ mv ../../dist/mf/mf.pool .
+ mv ../../dist/mf/mf.p $*.p
+
+inimf.ch: ../../dist/mf/mf.web
+
+trapmf.ch: inimf.ch ini_to_trap
+ ini_to_trap inimf.ch trapmf.ch
+
+%.o: %.p
+ ${PC} ${PFLAGS} -c $*.p
+
+trapmf.o: trapmf.p
+ ${PC} -g ${PFLAGS} -c trapmf.p
+
+inimf: inimf.o ext.o mf_arith.o mf_sunwin.o
+ pc ${PFLAGS} -o inimf inimf.o ext.o mf_arith.o mf_sunwin.o ${LIBS}
+
+trapmf: trapmf.o ext.o mf_arith.o
+ pc -g ${PFLAGS} -o trapmf trapmf.o ext.o mf_arith.o
+ cp ../../dist/mf/trap.mf .
+
+ext.o: ext.c ext.h ../h00vars.h ../mfpaths.h
+ cc ${CFLAGS} -c ext.c
+
+mf_arith.o: mf_arith.c
+mf_sunwin.o: mf_sunwin.c
+
+plain.base: ../../dist/lib/plain.mf ../lib/local.mf
+ -inimf plain \\input local \\dump
+
+install: # doit make install
+ mv inimf /usr/local/bin
+ rm /usr/local/bin/mf
+ ln /usr/local/bin/inimf /usr/local/bin/mf
+ make plain.base
+
+installtrap: # when the trap test is satisfactory
+ mv trap.mf trapin.log trap.log trap.fot trap.typ trap.pl ../../dist/mf
+
+clean:
+ rm -f *.p *.o *~ *.mf trapmf* trap.* trapin*
+ @echo "Remaining files should be:"
+ @echo "Makefile gftype.in mf.pool mf_window.h trap1.in"
+ @echo "ext.c ini_to_trap* mf_arith.c plain.base trap2.in"
+ @echo "ext.h inimf.ch mf_sunwin.c plain.log"
diff --git a/systems/knuth/local/mf-sparc/ext.c b/systems/knuth/local/mf-sparc/ext.c
new file mode 100644
index 0000000000..dfbf0b2bbb
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/ext.c
@@ -0,0 +1,457 @@
+/* external procedures called by MF */
+#include <sys/signal.h>
+#include <sys/time.h>
+#include "mfpaths.h" /* defines MAXINPATHCHARS, defaultinputpath, etc. */
+#include "h00vars.h"
+
+/* The following are for closing files */
+
+closea(f)
+ int *f; /* actually, file pointer, but it doesn't matter */
+{
+ close1(f);
+}
+
+closeb(f)
+ int *f; /* actually, file pointer, but it doesn't matter */
+{
+ close1(f);
+}
+
+closew(f)
+ int *f; /* actually, file pointer, but it doesn't matter */
+{
+ close1(f);
+}
+
+extern int interrupt; /* To be made nonzero to tell MF about interrupts */
+
+/*
+** catchint()
+**
+** Gets called when the user hits his interrupt key. Sets the global
+** "interrupt" nonzero, then sets it up so that the next interrupt will
+** also be caught here.
+**
+*/
+
+catchint()
+{
+ interrupt = 1;
+ signal(SIGINT,catchint);
+}
+
+/*
+** dateandtime(time, day, month, year)
+**
+** Stores minutes since midnight, current day, month and year into
+** *time, *day, *month and *year, respectively.
+**
+** Also, set things up so that catchint() will get control on interrupts.
+**
+*/
+
+dateandtime(minutes, day, month, year)
+int *minutes, *day, *month, *year;
+{
+ long clock;
+ struct tm *tmptr, *localtime();
+
+ clock = time(0);
+ tmptr = localtime(&clock);
+
+ *minutes = tmptr->tm_hour * 60 + tmptr->tm_min;
+ *day = tmptr->tm_mday;
+ *month = tmptr->tm_mon + 1;
+ *year = tmptr->tm_year + 1900;
+ signal(SIGINT,catchint);
+}
+
+
+/* fixed arrays are used to hold the paths, to avoid any possible problems
+ involving interaction of malloc and undump */
+
+char inputpath[MAXINPATHCHARS] = defaultinputpath;
+char basepath[MAXOTHPATHCHARS] = defaultbasepath;
+char poolpath[MAXOTHPATHCHARS] = defaultpoolpath;
+
+char *getenv();
+
+/*
+ * setpaths is called to set up the arrays inputpath, basepath, and
+ * poolpath as follows: if the user's environment has a value for the
+ * appropriate value, then use it; otherwise, leave the current value of
+ * the array (which may be the default path, or it may be the result of
+ * a call to setpaths on a previous run that was made the subject of
+ * an undump: this will give the maker of a preloaded MF the option of
+ * providing a new set of "default" paths.
+ *
+ * Note that we have to copy the string from the environment area, since
+ * that will change on the next run (which matters if this is for a
+ * preloaded MF).
+ */
+setpaths()
+{
+ register char *envpath;
+
+ if ((envpath = getenv("MFINPUTS")) != NULL)
+ excopypath(inputpath,envpath,MAXINPATHCHARS);
+ if ((envpath = getenv("MFBASES")) != NULL)
+ excopypath(basepath,envpath,MAXOTHPATHCHARS);
+ if ((envpath = getenv("MFPOOL")) != NULL)
+ excopypath(poolpath,envpath,MAXOTHPATHCHARS);
+}
+
+/*
+ * excopypath(s1,s2,n) copies at most n characters (including the null)
+ * from string s2 to string s1, giving an error message for paths
+ * that are too long.
+ */
+excopypath(s1,s2,n)
+ register char *s1,*s2;
+ register int n;
+{
+ while ((*s1++ = *s2++) != '\0')
+ if (--n == 0) {
+ fprintf(stderr, "! Environment search path is too big\n");
+ *--s1 = '\0';
+ return; /* let user continue with truncated path */
+ }
+}
+
+extern short buffer[],xord[];
+extern short last,first; /* pointers into buffer */
+
+/*
+ * lineread reads from the Pascal text file with iorec pointer filep
+ * into buffer[first], buffer[first+1],..., buffer[last-1] (and
+ * setting "last").
+ * Characters are read until a newline is found (which isn't put in the
+ * buffer) or until the next character would go into buffer[lastlim].
+ * The characters need to be translated, so really xord[c] is put into
+ * the buffer when c is read.
+ * If end-of-file is encountered, the funit field of *filep is set
+ * appropriately.
+ */
+lineread(filep, lastlim)
+struct iorec *filep;
+int lastlim;
+{
+ register c;
+ register short *cs; /* pointer into buffer where next char goes */
+ register FILE *iop; /* stdio-style FILE pointer */
+ int l; /* how many more chars are allowed before buffer overflow */
+ short *bf; /* hold address of buffer[first] */
+
+ iop = filep->fbuf;
+ bf = cs = &(buffer[first]);
+ l = lastlim-first;
+ /* overflow when next char would go into buffer[lastlim] */
+ while (--l>=0 && (c = getc(iop)) != EOF && c!='\n')
+ *cs++ = xord[c];
+ if (c == EOF)
+ filep->funit |= EOFF; /* we hit end-of-file */
+ last = first+cs-bf;
+}
+
+#define filenamesize 1024 /* should agree with inimf.ch */
+extern char nameoffile[],realnameoffile[]; /* these have size filenamesize */
+
+/*
+ * testaccess(amode,filepath)
+ *
+ * Test whether or not the file whose name is in the global nameoffile
+ * can be opened for reading (if mode=READACCESS)
+ * or writing (if mode=WRITEACCESS).
+ *
+ * The filepath argument is one of the ...FILEPATH constants defined below.
+ * If the filename given in nameoffile does not begin with '/', we try
+ * prepending all the ':'-separated areanames in the appropriate path to the
+ * filename until access can be made, if it ever can.
+ *
+ * The realnameoffile global array will contain the name that yielded an
+ * access success.
+ */
+
+#define READACCESS 4
+#define WRITEACCESS 2
+
+#define NOFILEPATH 0
+#define INPUTFILEPATH 1
+#define READFILEPATH 2
+#define BASEFILEPATH 4
+#define POOLFILEPATH 5
+
+bool
+testaccess(amode,filepath)
+ int amode,filepath;
+{
+ register bool ok;
+ register char *p;
+ char *curpathplace;
+ int f;
+
+ switch(filepath) {
+ case NOFILEPATH: curpathplace = NULL; break;
+ case INPUTFILEPATH: case READFILEPATH:
+ curpathplace = inputpath; break;
+ case BASEFILEPATH: curpathplace = basepath; break;
+ case POOLFILEPATH: curpathplace = poolpath; break;
+ }
+ if (nameoffile[0]=='/') /* file name has absolute path */
+ curpathplace = NULL;
+ do {
+ packrealnameoffile(&curpathplace);
+ if (amode==READACCESS)
+ /* use system call "access" to see if we could read it */
+ if (access(realnameoffile,READACCESS)==0) ok = TRUE;
+ else ok = FALSE;
+ else {
+ /* WRITEACCESS: use creat to see if we could create it, but close
+ the file again if we're OK, to let pc open it for real */
+ f = creat(realnameoffile,0666);
+ if (f>=0) ok = TRUE;
+ else ok = FALSE;
+ if (ok)
+ close(f);
+ }
+ } while (!ok && curpathplace != NULL);
+ if (ok) { /* pad realnameoffile with blanks, as Pascal wants */
+ for (p = realnameoffile; *p != '\0'; p++)
+ /* nothing: find end of string */ ;
+ while (p < &(realnameoffile[filenamesize]))
+ *p++ = ' ';
+ }
+ return (ok);
+}
+
+/*
+ * packrealnameoffile(cpp) makes realnameoffile contain the directory at *cpp,
+ * followed by '/', followed by the characters in nameoffile up until the
+ * first blank there, and finally a '\0'. The cpp pointer is left pointing
+ * at the next directory in the path.
+ * But: if *cpp == NULL, then we are supposed to use nameoffile as is.
+ */
+packrealnameoffile(cpp)
+ char **cpp;
+{
+ register char *p,*realname;
+
+ realname = realnameoffile;
+ if ((p = *cpp)!=NULL) {
+ while ((*p != ':') && (*p != '\0')) {
+ *realname++ = *p++;
+ if (realname == &(realnameoffile[filenamesize-1]))
+ break;
+ }
+ if (*p == '\0') *cpp = NULL; /* at end of path now */
+ else *cpp = p+1; /* else get past ':' */
+ *realname++ = '/'; /* separate the area from the name to follow */
+ }
+ /* now append nameoffile to realname... */
+ p = nameoffile;
+ while (*p != ' ') {
+ if (realname >= &(realnameoffile[filenamesize-1])) {
+ fprintf(stderr,"! Full file name is too long\n");
+ break;
+ }
+ *realname++ = *p++;
+ }
+ *realname = '\0';
+}
+
+/*
+** testeof(filep)
+**
+** Test whether or not the Pascal text file with iorec pointer filep
+** has reached end-of-file (when the only I/O on it is done with
+** lineread, above).
+** We may have to read the next character and unget it to see if perhaps
+** the end-of-file is next.
+*/
+
+bool
+testeof(filep)
+register struct iorec *filep;
+{
+ register char c;
+ register FILE *iop; /* stdio-style FILE pointer */
+ if (filep->funit & EOFF)
+ return(TRUE);
+ else { /* check to see if next is EOF */
+ iop = filep->fbuf;
+ c = getc(iop);
+ if (c == EOF)
+ return(TRUE);
+ else {
+ ungetc(c,iop);
+ return(FALSE);
+ }
+ }
+}
+
+
+/*
+** writegf(a,b)
+**
+** writegf is called to write gfbuf[a..b] to gffile
+** Unfortunately, gfbuf is declared as eight_bits, which in our
+** implementation means that two bytes are taken by each entry.
+** We only want to output the low order (first) byte of each pair.
+*/
+extern struct iorec gffile;
+extern short gfbuf[];
+writegf (a,b)
+ int a,b;
+{
+ register short *ptr,*final;
+ register FILE *iop;
+
+ iop=gffile.fbuf;
+ ptr= &(gfbuf[a]);
+ final= &(gfbuf[b]);
+ while (ptr<=final) {
+ putc((char) (*ptr & 0377), iop);
+ ptr += 1;
+ }
+ /* Note: The above code used to be machine dependent. By changing
+ * the declarations from "char *" to "short *" we get the machine
+ * to do its own byte ordering of the de-reference of "ptr" above.
+ * Then we AND off the low bits (now that it's been pulled from
+ * memory correctly) and cast it into a "char" for putc().
+ * --Peter Kessler's idea; explanation, AND, cast a la clp.
+ */
+}
+
+
+/*
+** close1(filep)
+** close1 does the proper things to pc's runtime system file data structure
+** to close a file
+*/
+close1(filep)
+
+ register struct iorec *filep;
+{
+ register struct iorec *next;
+
+ if (filep->fbuf != 0) {
+ if ((filep->funit & FDEF) == 0) {
+ next = (struct iorec *) &_fchain;
+ while (next->fchain != FILNIL
+ && next->fchain != filep)
+ next = next->fchain;
+ if (next->fchain != FILNIL)
+ next->fchain = next->fchain->fchain;
+
+ if (filep->fblk > PREDEF) {
+ fflush(filep->fbuf);
+ setbuf(filep->fbuf, NULL);
+ }
+ fclose(filep->fbuf);
+ if (ferror(filep->fbuf)) {
+/* ERROR("%s: Close failed\n",
+ filep->pfname); */
+ return;
+ }
+ filep->fbuf=0;
+ }
+ if ((filep->funit & TEMP) != 0 &&
+ unlink(filep->pfname)) {
+/* PERROR("Could not remove ", filep->pfname); */
+ return;
+ }
+ }
+}
+
+/*
+** The following procedure is due to sjc@s1-c.
+**
+** calledit(filename, fnlength, linenumber)
+**
+** MF84 can call this to implement the 'e' feature in error-recovery
+** mode, invoking a text editor on the erroneous source file.
+**
+** You should pass to "filename" the first character of the packed array
+** containing the filename, and to "fnlength" the size of the filename.
+**
+** Ordinarily, this invokes emacs. If you want a different
+** editor, create a shell environment variable MFEDIT containing
+** the string that invokes that editor, with "%s" indicating where
+** the filename goes and "%d" indicating where the decimal
+** linenumber (if any) goes. For example, a MFEDIT string for "vi" might be:
+**
+** setenv MFEDIT "/usr/bin/vi +%d %s"
+**
+*/
+
+ char dvalue[] = "emacs +%d %s";
+ char *mfeditvalue = &dvalue[0];
+
+ calledit(filename, fnlength, linenumber)
+ char *filename;
+ int fnlength, linenumber;
+ {
+ char *temp, *command, c;
+ int sdone, ddone, i;
+
+ sdone = ddone = 0;
+
+ /* Replace default with environment variable if possible. */
+ if (NULL != (temp = (char *) getenv("MFEDIT")))
+ mfeditvalue = temp;
+
+ /* Make command string containing envvalue, filename, and linenumber */
+ if (NULL ==
+ (command = (char *) malloc(strlen(mfeditvalue) + fnlength + 25))) {
+ fprintf(stderr, "! Not enough memory to issue editor command\n");
+ exit(1);
+ }
+ temp = command;
+ while ((c = *mfeditvalue++) != '\0') {
+ if (c == '%') {
+ switch (c = *mfeditvalue++) {
+ case 'd':
+ if (ddone) {
+ fprintf(stderr,
+ "! Line number cannot appear twice in editor command\n");
+ exit(1);
+ }
+ sprintf(temp, "%d", linenumber);
+ while (*temp != '\0')
+ temp++;
+ ddone = 1;
+ break;
+ case 's':
+ if (sdone) {
+ fprintf(stderr,
+ "! Filename cannot appear twice in editor command\n");
+ exit(1);
+ }
+ i = 0;
+ while (i < fnlength)
+ *temp++ = filename[i++] ^ 0x80; /* changed for 8-bit MF */
+ sdone = 1;
+ break;
+ case '\0':
+ *temp++ = '%';
+ mfeditvalue--; /* Back up to \0 to force termination. */
+ break;
+ default:
+ *temp++ = '%';
+ *temp++ = c;
+ break;
+ }
+ }
+ else
+ *temp++ = c;
+ }
+ *temp = '\0';
+
+ /* Execute command. */
+ if (0 != system(command))
+ fprintf(stderr, "! Trouble executing command %s\n", command);
+
+ /* Quit, indicating MF had found an error before you typed "e". */
+ exit(1);
+ }
diff --git a/systems/knuth/local/mf-sparc/ext.h b/systems/knuth/local/mf-sparc/ext.h
new file mode 100644
index 0000000000..7ff0e3bfdc
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/ext.h
@@ -0,0 +1,38 @@
+procedure exit(x : integer);
+ external;
+
+procedure closea(var f:text);
+ external;
+
+procedure closeb(var f:bytefile);
+ external;
+
+procedure closew(var f:wordfile);
+ external;
+
+procedure dateandtime(var minutes, day, month, year : integer);
+ external;
+
+procedure setpaths;
+ external;
+
+function testaccess(accessmode:integer; filepath:integer): boolean;
+ external;
+
+function testeof(var f: text): boolean;
+ external;
+
+procedure lineread(var f: text; lastlim: integer);
+ external;
+
+procedure writegf(a,b:integer);
+ external;
+
+procedure calledit(var filename: packedASCIIcode; fnlength, linenumber: integer);
+ external;
+
+function makefraction(p,q:integer):fraction;
+ external;
+
+function takefraction(q:integer;f:fraction):integer;
+ external;
diff --git a/systems/knuth/local/mf-sparc/gftype.in b/systems/knuth/local/mf-sparc/gftype.in
new file mode 100644
index 0000000000..9b48ee4cf9
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/gftype.in
@@ -0,0 +1,2 @@
+y
+y
diff --git a/systems/knuth/local/mf-sparc/ini_to_trap b/systems/knuth/local/mf-sparc/ini_to_trap
new file mode 100644
index 0000000000..c18984179f
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/ini_to_trap
@@ -0,0 +1,38 @@
+#! /bin/csh
+# A shell script to perform modifications on the changefile for inimf
+# to make a changefile for trapmf (used to test mf).
+#
+# To use it, say
+# ini_to_trap inimf.ch trapmf.ch
+#
+ed - $1 <<edscriptend
+/debug=/
+//
+s/@{//p
+/gubed=/
+s/@t@>@}//p
+/@!mem_max=/
+//
+s/[0-9][0-9]*/3000/p
+/@!error_line=/
+s/[0-9][0-9]*/64/p
+/@!half_error_line=/
+s/[0-9][0-9]*/32/p
+/@!max_print_line=/
+s/[0-9][0-9]*/72/p
+/@!screen_width=/
+s/[0-9][0-9]*/100/p
+/@!screen_depth=/
+s/[0-9][0-9]*/200/p
+/@!gf_buf_size=/
+s/[0-9][0-9]*/8/p
+/@d mem_min=/
+//
+s/-[0-9]*/0/p
+/@d mem_top==/
+s/[0-9][0-9]*/3000/p
+/% BEGIN HOOK FOR THE TRAP TEST/
+.+1,.+5s/%//
+.+1,/% END HOOK FOR THE TRAP TEST/d
+w $2
+edscriptend
diff --git a/systems/knuth/local/mf-sparc/inimf.ch b/systems/knuth/local/mf-sparc/inimf.ch
new file mode 100644
index 0000000000..271532c7b6
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/inimf.ch
@@ -0,0 +1,1505 @@
+% Derived from INITEX.CH for Berkeley Unix TeX 1.1, by Howard Trickey
+% and Pavel Curtis
+
+% Modification History:
+%
+% brought up to version 2.7182 on 8/8/98 --- don
+% brought up to version 2.718 on 3/8/95 --- don
+% UNIXexit convention switched 2/21/93 --- don
+% tfm_out needed to be corrected for new Pascal compiler 7/18/92 --- don
+% brought up to version 2.71 on 9/20/91 --- don
+% brought up to version 2.7 on 9/6/90 --- don
+% fixed max_buf_stack logic (it was one too high) on 1/22/90 --- don
+% brought up to version 1.9 on 12/20/89 --- don
+% brought up to version 1.8 on 10/14/89 --- don
+% 8-bit modifications made 9/11/89 --- don
+%
+% don adapted everything for SunOS, MF Version 1.7, on 8/12/89
+% Module numbers changed to match Volume D
+% Changes made more consistent with initex.ch
+% Window code merged in, with hooks to remove it for the TRAP test
+%
+% Revision 1.3 87/03/07 21:15:21 mackay
+%
+% Minor changes found on archive version on SCORE
+% (max_in_open increased to 10. -- 88/02/07 PAM)
+%
+% Revision 1.2 86/09/29 21:46:43 mackay
+%
+% Made no-debug the default, and changed version number
+% to correspond with improved mf.web file
+% (Got rid of debug code to avoid bug in range check
+% code of VAX4.3 BSD and SUN3 version 3.x Os pc interpreter)
+%
+% Revision 1.0 86/01/31 15:46:08 richards
+% Released for MF 1.0;
+%
+% Incorporates: New binary I/O library, separate optimized
+% arithmetic for takefraction/makefraction, new graphics interface
+%
+% Revision 0.999999.1.2 86/01/28 19:49:38 richards
+% Added:
+% variable "dummy" to routine initterm() because SUN PC compiler
+% loops with only i,j,k defined. Argh!
+%
+% Revision 0.999999.1.1 86/01/21 23:05:16 richards
+% First cut for MF 1.0
+%
+% Revision 0.999999 86/01/13 00:40:25 richards
+% Released for 0.999999:
+% added OTHERCASES sentinel
+% revised WINDOW interface and include files
+%
+% Revision 0.99999 85/12/09 20:23:35 richards
+% Version for 0.99999
+%
+% Revision 0.9999 85/10/21 20:48:24 richards
+% Released for MF version 0.9999
+%
+% Revision 0.999 85/10/18 21:33:44 richards
+% Version that works with 0.999 MF (Never released)
+%
+% Revision 0.91 85/05/16 10:58:13 richards
+% Released for MF version 0.91
+%
+% Revision 0.81 85/05/05 12:24:08 richards
+% Released for MF version 0.81
+%
+% Revision 0.77 85/03/11 20:23:37 richards
+% Released for MF version 0.77
+%
+% Revision 0.6.1.1 85/02/12 20:12:32 richards
+% First edit for 0.76
+%
+% Revision 0.6 85/02/08 00:52:40 richards
+% Distribution version for MF 0.6
+%
+% Revision 0.0.2.1 84/12/06 03:43:33 richards
+% Edited to work with 0.4 -- still needs to have section numbers re-done
+% before release.
+%
+% Revision 0.0 84/11/05 00:50:38 richards
+% Base version (first cut) for MetaFont 0.0
+%
+%
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [0] WEAVE: only print changes
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+\def\botofcontents{\vskip 0pt plus 1fil minus 1.5in}
+@y
+\def\botofcontents{\vskip 0pt plus 1fil minus 1.5in}
+\let\maybe=\iffalse
+\def\title{{\logo opqrstuq} changes for SunOS}
+\def\glob{13}\def\gglob{20, 25} % these are defined in module 1
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [1.2] banner line
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@d banner=='This is METAFONT, Version 2.7182' {printed when \MF\ starts}
+@y
+@d banner=='This is METAFONT, Version 2.7182 for SunOS'
+ {printed when \MF\ starts}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [1.4] program header, include ext.h for C routine linkage
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+Actually the heading shown here is not quite normal: The |program| line
+does not mention any |output| file, because \ph\ would ask the \MF\ user
+to specify a file name if |output| were specified here.
+@^system dependencies@>
+
+@d mtype==t@&y@&p@&e {this is a \.{WEB} coding trick:}
+@y
+@d mtype==t@&y@&p@&e {this is a \.{WEB} coding trick:}
+@d standard_input==i@&n@&p@&u@&t {and another}
+@z
+@x
+program MF; {all file names are defined dynamically}
+@y
+program MF(standard_input,output); {other file names are defined dynamically}
+@z
+@x
+var @<Global variables@>@/
+@y
+var @<Global variables@>@/
+@#
+@\@=#include "ext.h"@>@\ {declarations for external C procedures}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [1.7] debug..gubed, stat..tats
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@d debug==@{ {change this to `$\\{debug}\equiv\null$' when debugging}
+@d gubed==@t@>@} {change this to `$\\{gubed}\equiv\null$' when debugging}
+@y
+@d debug==@{
+@d gubed==@t@>@}
+@z
+% (I will use the debug code only in the trap test)
+@x
+@d stat==@{ {change this to `$\\{stat}\equiv\null$' when gathering
+ usage statistics}
+@d tats==@t@>@} {change this to `$\\{tats}\equiv\null$' when gathering
+ usage statistics}
+@y
+@d stat==
+@d tats==
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [1.8] init..tini
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@d init== {change this to `$\\{init}\equiv\.{@@\{}$' in the production version}
+@d tini== {change this to `$\\{tini}\equiv\.{@@\}}$' in the production version}
+@y
+@d init==
+@d tini==
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [1.9] compiler directives
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@{@&$C-,A+,D-@} {no range check, catch arithmetic overflow, no debug overhead}
+@!debug @{@&$C+,D+@}@+ gubed {but turn everything on when debugging}
+@y
+@=(*$C-*)@> {no range check}
+@!debug @=(*$C+*)@> @+ gubed {but turn everything on when debugging}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [1.10] othercases, feature of Sun Pascal
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@d othercases == others: {default for cases not listed explicitly}
+@y
+@d othercases == otherwise {default for cases not listed explicitly}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [1.11] compile-time constants
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@<Constants...@>=
+@!mem_max=30000; {greatest index in \MF's internal |mem| array;
+ must be strictly less than |max_halfword|;
+ must be equal to |mem_top| in \.{INIMF}, otherwise |>=mem_top|}
+@!max_internal=100; {maximum number of internal quantities}
+@!buf_size=500; {maximum number of characters simultaneously present in
+ current lines of open files; must not exceed |max_halfword|}
+@!error_line=72; {width of context lines on terminal error messages}
+@!half_error_line=42; {width of first lines of contexts in terminal
+ error messages; should be between 30 and |error_line-15|}
+@!max_print_line=79; {width of longest text lines output; should be at least 60}
+@!screen_width=768; {number of pixels in each row of screen display}
+@!screen_depth=1024; {number of pixels in each column of screen display}
+@!stack_size=30; {maximum number of simultaneous input sources}
+@!max_strings=2000; {maximum number of strings; must not exceed |max_halfword|}
+@!string_vacancies=8000; {the minimum number of characters that should be
+ available for the user's identifier names and strings,
+ after \MF's own error messages are stored}
+@!pool_size=32000; {maximum number of characters in strings, including all
+ error messages and help texts, and the names of all identifiers;
+ must exceed |string_vacancies| by the total
+ length of \MF's own strings, which is currently about 22000}
+@!move_size=5000; {space for storing moves in a single octant}
+@!max_wiggle=300; {number of autorounded points per cycle}
+@!gf_buf_size=800; {size of the output buffer, must be a multiple of 8}
+@!file_name_size=40; {file names shouldn't be longer than this}
+@!pool_name='MFbases:MF.POOL ';
+ {string of length |file_name_size|; tells where the string pool appears}
+@y
+@<Constants...@>=
+@!mem_max=30000; {greatest index in \MF's internal |mem| array;
+ must be strictly less than |max_halfword|;
+ must be equal to |mem_top| in \.{INIMF}, otherwise |>=mem_top|}
+@!max_internal=100; {maximum number of internal quantities}
+@!buf_size=500; {maximum number of characters simultaneously present in
+ current lines of open files; must not exceed |max_halfword|}
+@!error_line=79; {width of context lines on terminal error messages}
+@!half_error_line=50; {width of first lines of contexts in terminal
+ error messages; should be between 30 and |error_line-15|}
+@!max_print_line=79; {width of longest text lines output; should be at least 60}
+@!screen_width=1024; {number of pixels in each row of screen display}
+@!screen_depth=800; {number of pixels in each column of screen display}
+@!stack_size=30; {maximum number of simultaneous input sources}
+@!max_strings=3000; {maximum number of strings; must not exceed |max_halfword|}
+@!string_vacancies=18000; {the minimum number of characters that should be
+ available for the user's identifier names and strings,
+ after \MF's own error messages are stored}
+@!pool_size=42000; {maximum number of characters in strings, including all
+ error messages and help texts, and the names of all identifiers;
+ must exceed |string_vacancies| by the total
+ length of \MF's own strings, which is currently about 22000}
+@!move_size=5000; {space for storing moves in a single octant}
+@!max_wiggle=300; {number of autorounded points per cycle}
+@!gf_buf_size=800; {size of the output buffer, must be a multiple of 8}
+@!file_name_size=1024; {file names shouldn't be longer than this}
+@!pool_name='mf.pool';
+ {string of length |file_name_size|; tells where the string pool appears}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [1.12] sensitive compile-time constants
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@d mem_min=0 {smallest index in the |mem| array, must not be less
+ than |min_halfword|}
+@d mem_top==30000 {largest index in the |mem| array dumped by \.{INIMF};
+ must be substantially larger than |mem_min|
+ and not greater than |mem_max|}
+@d hash_size=2100 {maximum number of symbolic tokens,
+ must be less than |max_halfword-3*param_size|}
+@d hash_prime=1777 {a prime number equal to about 85\pct! of |hash_size|}
+@d max_in_open=6 {maximum number of input files and error insertions that
+ can be going on simultaneously}
+@d param_size=150 {maximum number of simultaneous macro parameters}
+@y
+@d mem_min==-30000 {smallest index in the |mem| array, must not be less
+ than |min_halfword|}
+@d mem_top==30000 {largest index in the |mem| array dumped by \.{INIMF};
+ must be substantially larger than |mem_min|
+ and not greater than |mem_max|}
+@d hash_size=2100 {maximum number of symbolic tokens,
+ must be less than |max_halfword-3*param_size|}
+@d hash_prime=1777 {a prime number equal to about 85\pct! of |hash_size|}
+@d max_in_open=10 {maximum number of input files and error insertions that
+ can be going on simultaneously. Enlarged for Silvio Levy's Greek}
+@d param_size=150 {maximum number of simultaneous macro parameters}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [1.22] Permissive input
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@^character set dependencies@>
+@^system dependencies@>
+
+@<Set init...@>=
+for i:=0 to @'37 do xchr[i]:=' ';
+for i:=@'177 to @'377 do xchr[i]:=' ';
+@y
+@^character set dependencies@>
+@^system dependencies@>
+
+@d tab = @'11 { ASCII horizontal tab }
+@d form_feed = @'14 { ASCII form-feed }
+
+@<Set init...@>=
+for i:=0 to @'37 do xchr[i]:=chr(i);
+for i:=@'177 to @'377 do xchr[i]:=chr(i);
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [3.24] file types
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+The program actually makes use also of a third kind of file, called a
+@y
+The pc compiler on Berkeley {\mc UNIX} won't pack a range into one byte unless
+the lower bound is |-128| or more, and the upper bound is |127| or less.
+This applies to files, too. To make the program work with compiler range
+checking turned on, we'll have to adjust |eight_bits| codes by sometimes
+adding or subtracting |256|.
+Note that |eight_bits| really takes 16 bits here.
+
+The program actually makes use also of a third kind of file, called a
+@z
+@x
+@!alpha_file=packed file of text_char; {files that contain textual data}
+@!byte_file=packed file of eight_bits; {files that contain binary data}
+@y
+@!alpha_file=t@&e@&x@&t; {files that contain textual data}
+@!byte_file=packed file of -128..127; {files that contain binary data}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [3.25] add real_name_of_file array for search path resolution
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+is crucial for our purposes. We shall assume that |name_of_file| is a variable
+of an appropriate type such that the \PASCAL\ run-time system being used to
+implement \MF\ can open a file whose external name is specified by
+|name_of_file|.
+@^system dependencies@>
+
+@<Glob...@>=
+@!name_of_file:packed array[1..file_name_size] of char;@;@/
+ {on some systems this may be a \&{record} variable}
+@!name_length:0..file_name_size;@/{this many characters are actually
+ relevant in |name_of_file| (the rest are blank)}
+@y
+is crucial for our purposes. We shall assume that |name_of_file| is a variable
+of an appropriate type such that the \PASCAL\ run-time system being used to
+implement \MF\ can open a file whose external name is specified by
+|name_of_file|.
+The Berkeley {\mc UNIX} version uses search paths to look for files to open.
+We use |real_name_of_file| to hold the |name_of_file| with a directory
+name from the path in front of it.
+@^system dependencies@>
+
+@<Glob...@>=
+@!name_of_file,@!real_name_of_file:packed array[1..file_name_size] of char;
+@;@/
+@!name_length:0..file_name_size;@/{this many characters are actually
+ relevant in |name_of_file| (the rest are blank)}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [3.26] file opening
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@ The \ph\ compiler with which the present version of \MF\ was prepared has
+extended the rules of \PASCAL\ in a very convenient way. To open file~|f|,
+we can write
+$$\vbox{\halign{#\hfil\qquad&#\hfil\cr
+|reset(f,@t\\{name}@>,'/O')|&for input;\cr
+|rewrite(f,@t\\{name}@>,'/O')|&for output.\cr}}$$
+The `\\{name}' parameter, which is of type `\ignorespaces|packed
+array[@t\<\\{any}>@>] of text_char|', stands for the name of
+the external file that is being opened for input or output.
+Blank spaces that might appear in \\{name} are ignored.
+
+The `\.{/O}' parameter tells the operating system not to issue its own
+error messages if something goes wrong. If a file of the specified name
+cannot be found, or if such a file cannot be opened for some other reason
+(e.g., someone may already be trying to write the same file), we will have
+|@!erstat(f)<>0| after an unsuccessful |reset| or |rewrite|. This allows
+\MF\ to undertake appropriate corrective action.
+@:PASCAL H}{\ph@>
+@^system dependencies@>
+
+\MF's file-opening procedures return |false| if no file identified by
+|name_of_file| could be opened.
+
+@d reset_OK(#)==erstat(#)=0
+@d rewrite_OK(#)==erstat(#)=0
+
+@p function a_open_in(var @!f:alpha_file):boolean;
+ {open a text file for input}
+begin reset(f,name_of_file,'/O'); a_open_in:=reset_OK(f);
+end;
+@#
+function a_open_out(var @!f:alpha_file):boolean;
+ {open a text file for output}
+begin rewrite(f,name_of_file,'/O'); a_open_out:=rewrite_OK(f);
+end;
+@#
+function b_open_out(var @!f:byte_file):boolean;
+ {open a binary file for output}
+begin rewrite(f,name_of_file,'/O'); b_open_out:=rewrite_OK(f);
+end;
+@#
+function w_open_in(var @!f:word_file):boolean;
+ {open a word file for input}
+begin reset(f,name_of_file,'/O'); w_open_in:=reset_OK(f);
+end;
+@#
+function w_open_out(var @!f:word_file):boolean;
+ {open a word file for output}
+begin rewrite(f,name_of_file,'/O'); w_open_out:=rewrite_OK(f);
+end;
+@y
+@ The \ph\ compiler with which the present version of \MF\ was prepared has
+extended the rules of \PASCAL\ in a very convenient way for file opening.
+Berkeley {\mc UNIX} \PASCAL\ isn't nearly as nice as \ph.
+Normally, it bombs out if a file open fails.
+An external C procedure, |test_access| is used to check whether or not the
+open will work. It is declared in the ``ext.h'' include file, and it returns
+|true| or |false|. The |name_of_file| global holds the file name whose access
+is to be tested.
+The first parameter for |test_access| is the access mode,
+one of |read_access_mode| or |write_access_mode|.
+
+We also implement path searching in |test_access|: its second parameter is
+one of the ``file path'' constants defined below. If |name_of_file|
+doesn't start with |'/'| then |test_access| tries prepending pathnames
+from the appropriate path list until success or the end of path list
+is reached.
+On return, |real_name_of_file| contains the original name with the path
+that succeeded (if any) prepended. It is the name used in the various
+open procedures.
+
+Note that |a_open_in| has been redefined to take an additional argument,
+which should be one of the ``file path'' specifiers.
+Path searching is not done for output files.
+
+@d read_access_mode=4 {``read'' mode for |test_access|}
+@d write_access_mode=2 {``write'' mode for |test_access|}
+
+@d no_file_path=0 {no path searching should be done}
+@d input_file_path=1 {path specifier for \.{\\input} files}
+@d base_file_path=4 {path specifier for base files}
+@d pool_file_path=5 {path specifier for the pool file}
+
+@p function a_open_in(var @!f:alpha_file;@!path_specifier:integer):boolean;
+ {open a text file for input}
+var @!ok:boolean;
+begin
+if test_access(read_access_mode,path_specifier) then
+ begin reset(f,real_name_of_file); ok:=true@+end
+else
+ ok:=false;
+a_open_in:=ok;
+end;
+@#
+function a_open_out(var @!f:alpha_file):boolean;
+ {open a text file for output}
+var @!ok:boolean;
+begin
+if test_access(write_access_mode,no_file_path) then
+ begin rewrite(f,real_name_of_file); ok:=true @+end
+else ok:=false;
+a_open_out:=ok;
+end;
+@#
+function b_open_out(var f:byte_file):boolean;
+ {open a binary file for output}
+var @!ok:boolean;
+begin
+if test_access(write_access_mode,no_file_path) then
+ begin rewrite(f,real_name_of_file); ok:=true @+end
+else ok:=false;
+b_open_out:=ok;
+end;
+@#
+function w_open_in(var @!f:word_file):boolean;
+ {open a word file for input}
+var @!ok:boolean;
+begin
+if test_access(read_access_mode,base_file_path) then
+ begin reset(f,real_name_of_file); ok:=true @+end
+else ok:=false;
+w_open_in:=ok;
+end;
+@#
+function w_open_out(var @!f:word_file):boolean;
+ {open a word file for output}
+var @!ok:boolean;
+begin
+if test_access(write_access_mode,no_file_path) then
+ begin rewrite(f,name_of_file); ok:=true @+end
+else ok:=false;
+w_open_out:=ok;
+end;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [3.27] file closing
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+This makes |f| available to be opened again, if desired; and if |f| was used for
+output, the |close| operation makes the corresponding external file appear
+on the user's area, ready to be read.
+
+@p procedure a_close(var @!f:alpha_file); {close a text file}
+begin close(f);
+end;
+@#
+procedure b_close(var @!f:byte_file); {close a binary file}
+begin close(f);
+end;
+@#
+procedure w_close(var @!f:word_file); {close a word file}
+begin close(f);
+end;
+@y
+This makes |f| available to be opened again, if desired; and if |f| was used for
+output, the |close| operation makes the corresponding external file appear
+on the user's area, ready to be read.
+
+With the pc library, files will be automatically closed when the program stops
+and when one reopens them.
+There is, however, the problem of opening a file and writing it, and then
+wanting to read it again, but from a different file variable.
+For this purpose we use external procedures |close_a|, |close_b|, and
+|close_w|.
+
+@p procedure a_close(var f:alpha_file); {close a text file}
+begin close_a(f);
+end;
+@#
+procedure b_close(var f:byte_file); {close a binary file}
+begin close_b(f);
+end;
+@#
+procedure w_close(var f:word_file); {close a word file}
+begin close_w(f);
+end;
+
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [3.30] faster version of input_ln
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+Standard \PASCAL\ says that a file should have |eoln| immediately
+before |eof|, but \MF\ needs only a weaker restriction: If |eof|
+occurs in the middle of a line, the system function |eoln| should return
+a |true| result (even though |f^| will be undefined).
+
+@p function input_ln(var @!f:alpha_file;@!bypass_eoln:boolean):boolean;
+ {inputs the next line or returns |false|}
+var @!last_nonblank:0..buf_size; {|last| with trailing blanks removed}
+begin if bypass_eoln then if not eof(f) then get(f);
+ {input the first character of the line into |f^|}
+last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
+if eof(f) then input_ln:=false
+else begin last_nonblank:=first;
+ while not eoln(f) do
+ begin if last>=max_buf_stack then
+ begin max_buf_stack:=last+1;
+ if max_buf_stack=buf_size then
+ @<Report overflow of the input buffer, and abort@>;
+ end;
+ buffer[last]:=xord[f^]; get(f); incr(last);
+ if buffer[last-1]<>" " then last_nonblank:=last;
+ end;
+ last:=last_nonblank; input_ln:=true;
+ end;
+end;
+@y
+Standard \PASCAL\ says that a file should have |eoln| immediately
+before |eof|, but \MF\ needs only a weaker restriction: If |eof|
+occurs in the middle of a line, the system function |eoln| should return
+a |true| result (even though |f^| will be undefined).
+
+With Berkeley {\mc UNIX} we call an external C procedure, |line_read|.
+That routine fills |buffer| from |first| onwards with the |xord|'ed values
+of the next line, setting |last| appropriately. It will stop if
+|last=buf_size|, and the following will cause an ``overflow'' abort.
+We ignore the |bypass_eoln| argument, since the |line_read| procedure
+will have handled bypassing the end-of-line in its previous call, if
+there was one.
+
+If one uses |input_ln| on a file, the normal |read|
+and |get| routines shouldn't be used, nor the |eof| and |eoln| tests.
+End of file can be tested with the external function |test_eof|.
+
+@p function input_ln(var f:alpha_file;@!bypass_eoln:boolean):boolean;
+ {inputs the next line or returns |false|}
+label done;
+begin
+last:=first; {cf.\ Matthew 19\thinspace:\thinspace30}
+if test_eof(f) then input_ln:=false
+else begin last:=first;
+ line_read(f,buf_size);
+ if last>max_buf_stack then begin
+ max_buf_stack:=last;
+ if max_buf_stack>=buf_size then
+ @<Report overflow of the input buffer, and abort@>;
+ end;
+ loop@+ begin if last=first then goto done;
+ if buffer[last-1]<>" " then goto done;
+ decr(last);
+ end;
+done: input_ln:=true;
+ end;
+end;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [3.31] term_in/out are input,output
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@ The user's terminal acts essentially like other files of text, except
+that it is used both for input and for output. When the terminal is
+considered an input file, the file variable is called |term_in|, and when it
+is considered an output file the file variable is |term_out|.
+@^system dependencies@>
+
+@<Glob...@>=
+@!term_in:alpha_file; {the terminal as an input file}
+@!term_out:alpha_file; {the terminal as an output file}
+@y
+@ The user's terminal acts essentially like other files of text, except
+that it is used both for input and for output. When the terminal is
+considered an input file, the file is called |term_in|, and when it
+is considered an output file the file is |term_out|.
+For Berkeley {\mc UNIX} we use |standard_input| and |output| for these
+files, as were declared in the program header. The former name
+|standard_input| was defined using a web trick so that ``input'' is
+produced in the Pascal file.
+
+@d term_in==standard_input {the terminal as an input file}
+@d term_out==output {the terminal as an output file}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [3.32] don't need to open terminal files
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@ Here is how to open the terminal files
+in \ph. The `\.{/I}' switch suppresses the first |get|.
+@^system dependencies@>
+
+@d t_open_in==reset(term_in,'TTY:','/O/I') {open the terminal for text input}
+@d t_open_out==rewrite(term_out,'TTY:','/O') {open the terminal for text output}
+@y
+@ Here is how to open the terminal files---do nothing.
+
+@d t_open_in == {input already open for text input}
+@d t_open_out == {output already open for text output}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [3.33] flushing output
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+these operations can be specified in \ph:
+@^system dependencies@>
+
+@d update_terminal == break(term_out) {empty the terminal output buffer}
+@d clear_terminal == break_in(term_in,true) {clear the terminal input buffer}
+@d wake_up_terminal == do_nothing {cancel the user's cancellation of output}
+@y
+these operations can be specified with Berkeley {\mc UNIX}:
+@^system dependencies@>
+
+@d update_terminal == flush(output)
+@d clear_terminal == {nothing necessary on UNIX}
+@d wake_up_terminal == {nothing necessary on UNIX}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [3.36] rescanning the command line
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@ The following program does the required initialization
+without retrieving a possible command line.
+It should be clear how to modify this routine to deal with command lines,
+if the system permits them.
+@^system dependencies@>
+
+@p function init_terminal:boolean; {gets the terminal input started}
+label exit;
+begin t_open_in;
+loop@+begin wake_up_terminal; write(term_out,'**'); update_terminal;
+@.**@>
+ if not input_ln(term_in,true) then {this shouldn't happen}
+ begin write_ln(term_out);
+ write(term_out,'! End of file on the terminal... why?');
+@.End of file on the terminal@>
+ init_terminal:=false; return;
+ end;
+ loc:=first;
+ while (loc<last)and(buffer[loc]=" ") do incr(loc);
+ if loc<last then
+ begin init_terminal:=true;
+ return; {return unless the line was all blank}
+ end;
+ write_ln(term_out,'Please type the name of your input file.');
+ end;
+exit:end;
+@y
+@ The following program does the required initialization
+and also retrieves a possible command line.
+@^system dependencies@>
+
+@p
+function init_terminal:boolean; {gets the terminal input started}
+label exit;
+
+var
+ dummy, i, j, k: integer;
+ arg: packed array[1..100] of char;
+
+begin
+ t_open_in;
+ if argc > 1 then begin
+ last := first;
+ for i := 1 to argc - 1 do begin
+ argv(i, arg);
+ j := 1;
+ k := 100; {find last non-blank char in arg}
+ while (k > 1) and (arg[k] = ' ') do@/
+ decr(k);
+ while (j <= k) do begin
+ buffer[last] := xord[arg[j]];
+ incr(j); incr(last);
+ end;
+ if k > 1 then begin
+ buffer[last] := xord[' '];
+ incr(last);
+ end;
+ end;
+ if last > first then begin
+ loc := first;
+ init_terminal := true;
+ return;
+ end;
+ end;
+ loop@+begin
+ wake_up_terminal; write(term_out, '**'); update_terminal;
+@.**@>
+ if not input_ln(term_in,true) then begin {this shouldn't happen}
+ write_ln(term_out);
+ write_ln(term_out, '! End of file on the terminal... why?');
+@.End of file on the terminal@>
+ init_terminal:=false;
+ return;
+ end;
+
+ loc:=first;
+ while (loc<last)and(buffer[loc]=" ") do
+ incr(loc);
+
+ if loc<last then begin
+ init_terminal:=true;
+ return; {return unless the line was all blank}
+ end;
+ write_ln(term_out, 'Please type the name of your input file.');
+@.Please type the name...@>
+ end;
+exit:
+end;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [4.51] a_open_in of pool file needs path specifier
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+if a_open_in(pool_file) then
+@y
+if a_open_in(pool_file,pool_file_path) then
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [4.51,52,53] make MF.POOL lowercase in messages
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+else bad_pool('! I can''t read MF.POOL.')
+@y
+else bad_pool('! I can''t read mf.pool.')
+@z
+@x
+begin if eof(pool_file) then bad_pool('! MF.POOL has no check sum.');
+@y
+begin if eof(pool_file) then bad_pool('! mf.pool has no check sum.');
+@z
+@x
+ bad_pool('! MF.POOL line doesn''t begin with two digits.');
+@y
+ bad_pool('! mf.pool line doesn''t begin with two digits.');
+@z
+@x
+ bad_pool('! MF.POOL check sum doesn''t have nine digits.');
+@y
+ bad_pool('! mf.pool check sum doesn''t have nine digits.');
+@z
+@x
+done: if a<>@$ then bad_pool('! MF.POOL doesn''t match; TANGLE me again.');
+@y
+done: if a<>@$ then bad_pool('! mf.pool doesn''t match; tangle me again.');
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [6.79] switch-to-editor option
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+line ready to be edited. But such an extension requires some system
+wizardry, so the present implementation simply types out the name of the
+file that should be
+edited and the relevant line number.
+@^system dependencies@>
+
+There is a secret `\.D' option available when the debugging routines haven't
+been commented~out.
+@^debugging@>
+@y
+line ready to be edited.
+We do this by calling the external procedure |calledit| with a pointer to
+the filename, its length, and the line number.
+However, here we just set up the variables that will be used as arguments,
+since we don't want to do the switch-to-editor until after \MF\ has closed
+its files.
+@^system dependencies@>
+
+There is a secret `\.D' option available when the debugging routines have
+not been commented out.
+@^debugging@>
+@d edit_file==input_stack[file_ptr]
+@z
+@x
+"E": if file_ptr>0 then
+ begin print_nl("You want to edit file ");
+@.You want to edit file x@>
+ slow_print(input_stack[file_ptr].name_field);
+ print(" at line "); print_int(line);@/
+ interaction:=scroll_mode; jump_out;
+@y
+"E": if file_ptr>0 then
+ begin
+ ed_name_start:=str_start[edit_file.name_field];
+ ed_name_length:=str_start[edit_file.name_field+1] -
+ str_start[edit_file.name_field];
+ edit_line:=line;
+ jump_out;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [7.107,108] replace make_fraction with external routine
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@p function make_fraction(@!p,@!q:integer):fraction;
+var @!f:integer; {the fraction bits, with a leading 1 bit}
+@!n:integer; {the integer part of $\vert p/q\vert$}
+@!negative:boolean; {should the result be negated?}
+@!be_careful:integer; {disables certain compiler optimizations}
+begin if p>=0 then negative:=false
+else begin negate(p); negative:=true;
+ end;
+if q<=0 then
+ begin debug if q=0 then confusion("/");@;@+gubed@;@/
+@:this can't happen /}{\quad \./@>
+ negate(q); negative:=not negative;
+ end;
+n:=p div q; p:=p mod q;
+if n>=8 then
+ begin arith_error:=true;
+ if negative then make_fraction:=-el_gordo@+else make_fraction:=el_gordo;
+ end
+else begin n:=(n-1)*fraction_one;
+ @<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>;
+ if negative then make_fraction:=-(f+n)@+else make_fraction:=f+n;
+ end;
+end;
+
+@ The |repeat| loop here preserves the following invariant relations
+between |f|, |p|, and~|q|:
+(i)~|0<=p<q|; (ii)~$fq+p=2^k(q+p_0)$, where $k$ is an integer and
+$p_0$ is the original value of~$p$.
+
+Notice that the computation specifies
+|(p-q)+p| instead of |(p+p)-q|, because the latter could overflow.
+Let us hope that optimizing compilers do not miss this point; a
+special variable |be_careful| is used to emphasize the necessary
+order of computation. Optimizing compilers should keep |be_careful|
+in a register, not store it in memory.
+@^inner loop@>
+
+@<Compute $f=\lfloor 2^{28}(1+p/q)+{1\over2}\rfloor$@>=
+f:=1;
+repeat be_careful:=p-q; p:=be_careful+p;
+if p>=0 then f:=f+f+1
+else begin double(f); p:=p+q;
+ end;
+until f>=fraction_one;
+be_careful:=p-q;
+if be_careful+p>=0 then incr(f)
+
+@y
+Under {\mc UNIX} \MF, we have replaced the \PASCAL\ version of |make_fraction|
+with either a C or assembly language equivalent for efficiency.
+
+@ This section was deleted when |make_fraction| was removed.
+
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [7.109,110,111] replace take_fraction with external version
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@p function take_fraction(@!q:integer;@!f:fraction):integer;
+var @!p:integer; {the fraction so far}
+@!negative:boolean; {should the result be negated?}
+@!n:integer; {additional multiple of $q$}
+@!be_careful:integer; {disables certain compiler optimizations}
+begin @<Reduce to the case that |f>=0| and |q>0|@>;
+if f<fraction_one then n:=0
+else begin n:=f div fraction_one; f:=f mod fraction_one;
+ if q<=el_gordo div n then n:=n*q
+ else begin arith_error:=true; n:=el_gordo;
+ end;
+ end;
+f:=f+fraction_one;
+@<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>;
+be_careful:=n-el_gordo;
+if be_careful+p>0 then
+ begin arith_error:=true; n:=el_gordo-p;
+ end;
+if negative then take_fraction:=-(n+p)
+else take_fraction:=n+p;
+end;
+
+@ @<Reduce to the case that |f>=0| and |q>0|@>=
+if f>=0 then negative:=false
+else begin negate(f); negative:=true;
+ end;
+if q<0 then
+ begin negate(q); negative:=not negative;
+ end;
+
+@ The invariant relations in this case are (i)~$\lfloor(qf+p)/2^k\rfloor
+=\lfloor qf_0/2^{28}+{1\over2}\rfloor$, where $k$ is an integer and
+$f_0$ is the original value of~$f$; (ii)~$2^k\L f<2^{k+1}$.
+@^inner loop@>
+
+@<Compute $p=\lfloor qf/2^{28}+{1\over2}\rfloor-q$@>=
+p:=fraction_half; {that's $2^{27}$; the invariants hold now with $k=28$}
+if q<fraction_four then
+ repeat if odd(f) then p:=half(p+q)@+else p:=half(p);
+ f:=half(f);
+ until f=1
+else repeat if odd(f) then p:=p+half(q-p)@+else p:=half(p);
+ f:=half(f);
+ until f=1
+
+@y
+Function |take_fraction| has also been replaced by an external routine.
+
+@ @<Reduce to the case that |f>=0| and |q>0|@>=
+if f>=0 then negative:=false
+else begin negate(f); negative:=true;
+ end;
+if q<0 then
+ begin negate(q); negative:=not negative;
+ end;
+
+@ This section was deleted when |take_fraction| was replaced by an
+external routine. (But the previous section was left in, because
+it is part of |take_scaled|, which follows.)
+
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [9.153] ranges for quarter,half words
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+can get 256 values into a quarterword only if the subrange is `|-128..127|'.
+
+The present implementation tries to accommodate as many variations as possible,
+so it makes few assumptions. If integers having the subrange
+`|min_quarterword..max_quarterword|' can be packed into a quarterword,
+and if integers having the subrange `|min_halfword..max_halfword|'
+can be packed into a halfword, everything should work satisfactorily.
+
+It is usually most efficient to have |min_quarterword=min_halfword=0|,
+so one should try to achieve this unless it causes a severe problem.
+The values defined here are recommended for most 32-bit computers.
+
+@d min_quarterword=0 {smallest allowable value in a |quarterword|}
+@d max_quarterword=255 {largest allowable value in a |quarterword|}
+@d min_halfword==0 {smallest allowable value in a |halfword|}
+@d max_halfword==65535 {largest allowable value in a |halfword|}
+@y
+can get 256 values into a quarterword only if the subrange is `|-128..127|'.
+
+For Berkeley {\mc UNIX} we need to do the |-128..127| kind of range.
+
+@d min_quarterword=-128 {smallest allowable value in a |quarterword|}
+@d max_quarterword=127 {largest allowable value in a |quarterword|}
+@d min_halfword==-32768 {smallest allowable value in a |halfword|}
+@d max_halfword==32767 {largest allowable value in a |halfword|}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [11.178] fix the word "free" so that it doesn't conflict with a runtime proc
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+been included. (You may want to decrease the size of |mem| while you
+@^debugging@>
+are debugging.)
+@y
+been included. (You may want to decrease the size of |mem| while you
+@^debugging@>
+are debugging.)
+
+@d free==free_arr
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [12.194] fix_date_and_time
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@ The following procedure, which is called just before \MF\ initializes its
+input and output, establishes the initial values of the date and time.
+@^system dependencies@>
+Since standard \PASCAL\ cannot provide such information, something special
+is needed. The program here simply specifies July 4, 1776, at noon; but
+users probably want a better approximation to the truth.
+
+Note that the values are |scaled| integers. Hence \MF\ can no longer
+be used after the year 32767.
+
+@p procedure fix_date_and_time;
+begin internal[time]:=12*60*unity; {minutes since midnight}
+internal[day]:=4*unity; {fourth day of the month}
+internal[month]:=7*unity; {seventh month of the year}
+internal[year]:=1776*unity; {Anno Domini}
+end;
+@y
+@ The following procedure, which is called just before \MF\ initializes its
+input and output, establishes the initial values of the date and time.
+It is calls an externally defined |date_and_time|, even though it could
+be done from Pascal.
+The external procedure also sets up interrupt catching.
+@^system dependencies@>
+
+Note that the values are |scaled| integers. Hence \MF\ can no longer
+be used after the year 32767.
+
+@p procedure fix_date_and_time;
+begin
+ date_and_time(internal[time],internal[day],internal[month],internal[year]);
+ internal[time] := internal[time] * unity;
+ internal[day] := internal[day] * unity;
+ internal[month] := internal[month] * unity;
+ internal[year] := internal[year] * unity;
+end;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [12.199] allow <tab> and <ff> as input
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+for k:=0 to " "-1 do char_class[k]:=invalid_class;
+for k:=127 to 255 do char_class[k]:=invalid_class;
+@y
+for k:=0 to " "-1 do char_class[k]:=invalid_class;
+for k:=127 to 255 do char_class[k]:=invalid_class;
+char_class[tab]:=space_class;
+char_class[form_feed]:=space_class;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [27.564] init_screen and update_screen are external C procs
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% BEGIN HOOK FOR THE TRAP TEST
+%@x
+%begin init_screen:=false;
+%@y
+%begin init_screen:=true;
+%@z
+@x
+The \PASCAL\ code here is a minimum version of |init_screen| and
+|update_screen|, usable on \MF\ installations that don't
+support screen output. If |init_screen| is changed to return |true|
+instead of |false|, the other routines will simply log the fact
+that they have been called; they won't really display anything.
+The standard test routines for \MF\ use this log information to check
+that \MF\ is working properly, but the |wlog| instructions should be
+removed from production versions of \MF.
+
+@p function init_screen:boolean;
+begin init_screen:=false;
+end;
+@#
+procedure update_screen; {will be called only if |init_screen| returns |true|}
+begin @!init wlog_ln('Calling UPDATESCREEN');@+tini {for testing only}
+end;
+
+@y
+We declare the screen functions
+for the {\mc UNIX} version of \MF\ in the following header file.
+
+@p
+@\@=#include "mf_window.h"@>@\ {declarations for external C procedures}
+
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [27.559] blank_rectangle is an external C proc
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+The commented-out code in the following procedure is for illustrative
+purposes only.
+@^system dependencies@>
+
+@p procedure blank_rectangle(@!left_col,@!right_col:screen_col;
+ @!top_row,@!bot_row:screen_row);
+var @!r:screen_row;
+@!c:screen_col;
+begin @{@+for r:=top_row to bot_row-1 do
+ for c:=left_col to right_col-1 do
+ screen_pixel[r,c]:=white;@+@}@/
+@!init wlog_cr; {this will be done only after |init_screen=true|}
+wlog_ln('Calling BLANKRECTANGLE(',left_col:1,',',
+ right_col:1,',',top_row:1,',',bot_row:1,')');@+tini
+end;
+
+@y
+@^system dependencies@>
+
+The procedure |blank_rectangle| has been declared an external routine
+for the {\mc UNIX} version of \MF\ in the header file above.
+
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [27.560] paint_row is an external C proc
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+The general idea is to paint blocks of pixels in alternate colors;
+the precise details are best conveyed by means of a \PASCAL\
+program (see the commented-out code below).
+@^system dependencies@>
+
+@p procedure paint_row(@!r:screen_row;@!b:pixel_color;var @!a:trans_spec;
+ @!n:screen_col);
+var @!k:screen_col; {an index into |a|}
+@!c:screen_col; {an index into |screen_pixel|}
+begin @{ k:=0; c:=a[0];
+repeat incr(k);
+ repeat screen_pixel[r,c]:=b; incr(c);
+ until c=a[k];
+ b:=black-b; {$|black|\swap|white|$}
+ until k=n;@+@}@/
+@!init wlog('Calling PAINTROW(',r:1,',',b:1,';');
+ {this is done only after |init_screen=true|}
+for k:=0 to n do
+ begin wlog(a[k]:1); if k<>n then wlog(',');
+ end;
+wlog_ln(')');@+tini
+end;
+
+@y
+@^system dependencies@>
+
+|Paint_row| has been declared an external routine in the {\mc UNIX} version
+of \MF\ in the header file above.
+
+@z
+% END HOOK FOR THE TRAP TEST
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.768] area and extension rules
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@ The file names we shall deal with for illustrative purposes have the
+following structure: If the name contains `\.>' or `\.:', the file area
+consists of all characters up to and including the final such character;
+otherwise the file area is null. If the remaining file name contains
+`\..', the file extension consists of all such characters from the first
+remaining `\..' to the end, otherwise the file extension is null.
+@^system dependencies@>
+
+We can scan such file names easily by using two global variables that keep track
+of the occurrences of area and extension delimiters:
+
+@<Glob...@>=
+@!area_delimiter:pool_pointer; {the most recent `\.>' or `\.:', if any}
+@!ext_delimiter:pool_pointer; {the relevant `\..', if any}
+@y
+@ The file names we shall deal with for SunOS have the
+following structure: If the name contains `\./', the file area
+consists of all characters up to and including the final such character;
+otherwise the file area is null. If the remaining file name contains
+`\..', the file extension consists of all such characters from the first
+remaining `\..' to the end, otherwise the file extension is null.
+@^system dependencies@>
+
+We can scan such file names easily by using two global variables that keep
+track of the occurrences of area and extension delimiters:
+
+@<Glob...@>=
+@!area_delimiter:pool_pointer; {the most recent `\./', if any}
+@!ext_delimiter:pool_pointer; {the most recent `\..', if any}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.769] MF area directories
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@d MF_area=="MFinputs:"
+@.MFinputs@>
+@y
+Under Berkeley {\mc UNIX}, the default paths are specified in a seprate
+file, `\.{mfpaths.h}'. The file opening procedures do path searching
+based either on those default paths, or on paths given by the user
+in ``environment'' variables.
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.771] more_name
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+begin if c=" " then more_name:=false
+else begin if (c=">")or(c=":") then
+@y
+begin if (c=" ")or(c=tab) then more_name:=false
+else begin if (c="/") then
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.775] default base
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@d base_default_length=18 {length of the |MF_base_default| string}
+@d base_area_length=8 {length of its area part}
+@d base_ext_length=5 {length of its `\.{.base}' part}
+@y
+Under Berkeley {\mc UNIX} we don't give the area part, instead depending
+on the path searching that will happen during file opening.
+
+@d base_default_length=10 {length of the |MF_base_default| string}
+@d base_area_length=0 {length of its area part}
+@d base_ext_length=5 {length of its `\.{.base}' part}
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.776] plain base location
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+MF_base_default:='MFbases:plain.base';
+@y
+MF_base_default:='plain.base';
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.779] w_open_in of base file needs to be called only once
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+ pack_buffered_name(0,loc,j-1); {try first without the system file area}
+ if w_open_in(base_file) then goto found;
+ pack_buffered_name(base_area_length,loc,j-1);
+ {now try the system base file area}
+ if w_open_in(base_file) then goto found;
+@y
+ pack_buffered_name(0,loc,j-1);
+ if w_open_in(base_file) then goto found;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.780] make_name_string
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+which simply makes a \MF\ string from the value of |name_of_file|, should
+ideally be changed to deduce the full name of file~|f|, which is the file
+most recently opened, if it is possible to do this in a \PASCAL\ program.
+@^system dependencies@>
+
+This routine might be called after string memory has overflowed, hence
+we dare not use `|str_room|'.
+
+@p function make_name_string:str_number;
+var @!k:1..file_name_size; {index into |name_of_file|}
+begin if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings) then
+ make_name_string:="?"
+else begin for k:=1 to name_length do append_char(xord[name_of_file[k]]);
+ make_name_string:=make_string;
+ end;
+end;
+@y
+which simply makes a \MF\ string from the value of |name_of_file|, should
+ideally be changed to deduce the full name of file~|f|, which is the file
+most recently opened, if it is possible to do this in a \PASCAL\ program.
+With the Berkeley {\mc UNIX} version, we know that |real_name_of_file|
+contains |name_of_file| prepended with the directory name that was found
+by path searching.
+If |real_name_of_file| starts with |'./'|, we don't use that part of the
+name, since {\mc UNIX} users understand that.
+@^system dependencies@>
+
+This routine might be called after string memory has overflowed, hence
+we dare not use `|str_room|'.
+
+@p function make_name_string:str_number;
+var @!k,@!kstart:1..file_name_size; {index into |name_of_file|}
+begin
+k:=1;
+while (k<file_name_size) and (xord[real_name_of_file[k]]<>" ") do
+ incr(k);
+name_length:=k-1; {the real |name_length|}
+if (pool_ptr+name_length>pool_size)or(str_ptr=max_strings) then
+ make_name_string:="?"
+else begin
+ if (xord[real_name_of_file[1]]=".") and (xord[real_name_of_file[2]]="/") then
+ kstart:=3
+ else
+ kstart:=1;
+ for k:=kstart to name_length do append_char(xord[real_name_of_file[k]]);
+ make_name_string:=make_string;
+ end;
+end;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.781] scan_file_name ignore leading tabs as well as spaces
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@p procedure scan_file_name;
+label done;
+begin begin_name;
+while buffer[loc]=" " do incr(loc);
+@y
+@p procedure scan_file_name;
+label done;
+begin begin_name;
+while (buffer[loc]=" ")or(buffer[loc]=tab) do incr(loc);
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.787] <Scan_file_name...> needs similar leading tab treatment
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@ @<Scan file name in the buffer@>=
+begin begin_name; k:=first;
+while (buffer[k]=" ")and(k<last) do incr(k);
+@y
+@ @<Scan file name in the buffer@>=
+begin begin_name; k:=first;
+while ((buffer[k]=" ")or(buffer[k]=tab))and(k<last) do incr(k);
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.793] a_open_in of input file needs path selector
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+ if a_open_in(cur_file) then goto done;
+ if cur_area="" then
+ begin pack_file_name(cur_name,MF_area,cur_ext);
+ if a_open_in(cur_file) then goto done;
+ end;
+@y
+ if a_open_in(cur_file,input_file_path) then goto done;
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [38.793] get rid of return of name to string pool
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+if name=str_ptr-1 then {we can conserve string pool space now}
+ begin flush_string(name); name:=cur_name;
+ end;
+@y
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [45.1133] writing the tfm file
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@d tfm_out(#)==write(tfm_file,#) {output one byte to |tfm_file|}
+@y
+@d tfm_out(#) ==write(tfm_file,((#+128) mod 256)-128)
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [47.1154] write_gf
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@<Declare generic font output procedures@>=
+procedure write_gf(@!a,@!b:gf_index);
+var k:gf_index;
+begin for k:=a to b do write(gf_file,gf_buf[k]);
+end;
+@y
+For Berkeley {\mc UNIX}, this is going to be handled by an external procedure,
+|writegf|, which will do the output using |fwrite|.
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [49.1204] Delete ready_already; also add call to set_paths;
+% also add call to exit() depending upon value of `history'
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@ Now this is really it: \MF\ starts and ends here.
+
+The initial test involving |ready_already| should be deleted if the
+\PASCAL\ runtime system is smart enough to detect such a ``mistake.''
+@y
+@ Now this is really it: \MF\ starts and ends here.
+
+Instead of testing |ready_already|, we give up the idea of a preloaded
+core image in favor of silently loading a format file based on the
+name by which this program has been invoked. For example, if the
+program is being called \.{mf}, we will load the \.{plain} base;
+if \.{cmmf}, we will load \.{cmmf.base}. On my machine the
+loading of a format isn't too slow. (I use the new string capabilities
+of Sun Pascal here; |my_name| will be declared {\bf varying} [100]
+{\bf of\/} |char|.)
+
+At the end of the job, we look at |history| to decide the correct
+exit code. We use 1 if |history <= warning_issued| and 0 otherwise.
+
+@d UNIXexit==e@&x@&i@&t
+@z
+
+@x
+t_open_out; {open the terminal for output}
+if ready_already=314159 then goto start_of_MF;
+@y
+t_open_out; {open the terminal for output}
+set_paths;
+@z
+@x
+start_of_MF: @<Initialize the output routines@>;
+@y
+start_of_MF: argv(0,my_name);
+if (my_name<>'inimf')and(my_name<>'trapmf') then
+ begin if my_name = 'mf' then name_of_file:='plain.base'
+ else name_of_file:=my_name+'.base';
+ if w_open_in(base_file) then
+ if not load_base_file then
+ begin w_close(base_file); goto final_end;
+ end
+ else w_close(base_file);
+ end;
+@<Initialize the output routines@>;
+@z
+
+@x
+final_end: ready_already:=0;
+@y
+final_end: ready_already:=0;
+if (history <= warning_issued) then
+ UNIXexit(0)
+else
+ UNIXexit(1);
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [49.1204] print new line before termination; switch to editor if nec.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+ slow_print(log_name); print_char(".");
+ end;
+ end;
+@y
+ slow_print(log_name); print_char(".");
+ end;
+ end;
+print_ln;
+if (ed_name_start<>0) and (interaction>batch_mode) then
+ calledit(str_pool[ed_name_start],ed_name_length,edit_line);
+@z
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+% [51.1214] add editor-switch variable to globals
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+@x
+@* \[51] System-dependent changes.
+This section should be replaced, if necessary, by any special
+modifications of the program
+that are necessary to make \MF\ work at a particular installation.
+It is usually best to design your change file so that all changes to
+previous sections preserve the section numbering; then everybody's version
+will be consistent with the published program. More extensive changes,
+which introduce new sections, can be inserted here; then only the index
+itself will get a new section number.
+@^system dependencies@>
+@y
+@* \[51] System-dependent changes.
+Here are the variables used to hold ``switch-to-editor'' information.
+And the omphaloskeptic variable too.
+@^system dependencies@>
+
+@<Global...@>=
+@!ed_name_start: pool_pointer;
+@!ed_name_length,@!edit_line: integer;
+@!my_name:varying [100] of char;
+
+@ The |ed_name_start| will be set to point into |str_pool| somewhere after
+its beginning if \MF\ is supposed to switch to an editor on exit.
+
+@<Set init...@>=
+ed_name_start:=0;
+@z
+
diff --git a/systems/knuth/local/mf-sparc/mf.pool b/systems/knuth/local/mf-sparc/mf.pool
new file mode 100644
index 0000000000..4f1478cac2
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/mf.pool
@@ -0,0 +1,824 @@
+11buffer size
+09pool size
+17number of strings
+03???
+28End of file on the terminal!
+02!
+42(That makes 100 errors; please try again.)
+02?
+60Type <return> to proceed, S to scroll future error messages,
+44R to run without stopping, Q to run quietly,
+23I to insert something,
+20E to edit your file,
+561 or ... or 9 to ignore the next 1 to 9 tokens of input,
+22H for help, X to quit.
+13OK, entering
+09batchmode
+11nonstopmode
+10scrollmode
+03...
+07insert>
+44I have just deleted some text, as you asked.
+48You can now delete more, or insert, or whatever.
+50Sorry, I don't know how to help in this situation.
+36Maybe you should try asking a human?
+42Sorry, I already gave what help I could...
+59An error might have occurred before I noticed any problems.
+45``If all else fails, read the instructions.''
+00
+14Emergency stop
+35METAFONT capacity exceeded, sorry [
+44If you really absolutely need more capacity,
+35you can ask a wizard to enlarge me.
+19This can't happen (
+59I'm broken. Please show this to someone who can fix can fix
+35I can't go on meeting you like this
+55One of your faux pas seems to have wounded me deeply...
+59in fact, I'm barely conscious. Please fix it and try again.
+12Interruption
+09You rang?
+57Try to insert some instructions for me (e.g.,`I show x'),
+43unless you just want to quit by typing `X'.
+09Missing `
+19' has been inserted
+19Arithmetic overflow
+59Uh, oh. A little while ago one of the quantities that I was
+59computing got too large, so I'm afraid your answers will be
+55somewhat askew. You'll probably have to adopt different
+54tactics next time. But I shall try to carry on anyway.
+15Square root of
+23 has been replaced by 0
+52Since I don't take square roots of negative numbers,
+52I'm zeroing this one. Proceed, with fingers crossed.
+24Pythagorean subtraction
+03+-+
+13Logarithm of
+48Since I don't take logs of non-positive numbers,
+27angle(0,0) is taken as zero
+54The `angle' between two identical points is undefined.
+16main memory size
+24AVAIL list clobbered at
+31Double-AVAIL list clobbered at
+24Doubly free location at
+12Bad flag at
+14New busy locs:
+05LINK(
+05INFO(
+07vacuous
+07boolean
+15unknown boolean
+06string
+14unknown string
+03pen
+11unknown pen
+10future pen
+04path
+12unknown path
+07picture
+15unknown picture
+09transform
+04pair
+13known numeric
+09dependent
+15proto-dependent
+07numeric
+11independent
+10token list
+10structured
+16unsuffixed macro
+14suffixed macro
+09undefined
+04true
+05false
+11nullpicture
+07nullpen
+07jobname
+10readstring
+09pencircle
+13normaldeviate
+03odd
+05known
+07unknown
+03not
+07decimal
+07reverse
+08makepath
+07makepen
+11totalweight
+03oct
+03hex
+05ASCII
+04char
+06length
+13turningnumber
+05xpart
+05ypart
+06xxpart
+06xypart
+06yxpart
+06yypart
+04sqrt
+04mexp
+04mlog
+04sind
+04cosd
+05floor
+14uniformdeviate
+10charexists
+05angle
+05cycle
+02++
+02or
+03and
+02<=
+02>=
+02<>
+07rotated
+07slanted
+06scaled
+07shifted
+11transformed
+07xscaled
+07yscaled
+07zscaled
+17intersectiontimes
+09substring
+07subpath
+13directiontime
+05point
+10precontrol
+11postcontrol
+09penoffset
+02..
+13tracingtitles
+16tracingequations
+15tracingcapsules
+14tracingchoices
+12tracingspecs
+11tracingpens
+15tracingcommands
+15tracingrestores
+13tracingmacros
+12tracingedges
+13tracingoutput
+12tracingstats
+13tracingonline
+04year
+05month
+03day
+04time
+08charcode
+07charext
+06charwd
+06charht
+06chardp
+06charic
+06chardx
+06chardy
+10designsize
+04hppp
+04vppp
+07xoffset
+07yoffset
+07pausing
+12showstopping
+10fontmaking
+08proofing
+09smoothing
+12autorounding
+11granularity
+06fillin
+12turningcheck
+12warningcheck
+12boundarychar
+09 at line
+14a bad variable
+02fi
+08endgroup
+06enddef
+06endfor
+13 INACCESSIBLE
+09hash size
+06EQUIV(
+02::
+03||:
+02:=
+05addto
+02at
+07atleast
+10begingroup
+08controls
+04cull
+04curl
+10delimiters
+07display
+08everyjob
+06exitif
+11expandafter
+04from
+08inwindow
+07interim
+03let
+11newinternal
+02of
+10openwindow
+10randomseed
+04save
+10scantokens
+07shipout
+06skipto
+04step
+03str
+07tension
+02to
+05until
+05token
+05 ETC.
+10 CLOBBERED
+11 IMPOSSIBLE
+12 NONEXISTENT
+04 BAD
+02[]
+05(EXPR
+07(SUFFIX
+05(TEXT
+02->
+03>->
+08<expr>->
+19<expr>of<primary>->
+10<suffix>->
+08<text>->
+07(SAVED)
+03var
+02xx
+02xy
+02yx
+02yy
+08%CAPSULE
+05part
+06struct
+11{restoring
+04Path
+07{open?}
+10..control?
+03 ..
+06{curl
+10..tension
+05 and
+11..controls
+02??
+16, before choices
+15, after choices
+23Some number got too big
+46The path that I just computed is out of range.
+53So it will probably look funny. Proceed, for a laugh.
+09path size
+14Edge structure
+04row
+02 |
+31Scaled picture would be too big
+50I can't yscale the picture as requested---it would
+45make some coordinates too large or too small.
+42Proceed, and I'll omit the transformation.
+50I can't xscale the picture as requested---it would
+15move table size
+13Tracing edges
+09 (weight
+21(No new edges added.)
+10Cycle spec
+24 % beginning in octant `
+19% entering octant `
+08 & cycle
+03ENE
+03NNE
+03NNW
+03WNW
+03WSW
+03SSW
+03SSE
+03ESE
+14 ..controls
+11 % segment
+02 (
+33, before subdivision into octants
+19, after subdivision
+43, after subdivision and double autorounding
+36, after subdivision and autorounding
+18Curve out of range
+56At least one of the coordinates in the path I'm about to
+56digitize was really huge (potentially bigger than 4095).
+40So I've cut it back to the maximum size.
+41The results will probably be pretty wild.
+19rounding table size
+11Pen polygon
+09 .. cycle
+04 ..
+16 (newly created)
+13Pen too large
+59The cycle you specified has a coordinate of 4095.5 or more.
+55So I've replaced it by the trivial path `(0,0)..cycle'.
+24Pen cycle must be convex
+59The cycle you specified either has consecutive equal points
+54or turns right or turns through more than 360 degrees.
+16pen polygon size
+09@ Octant
+07 offset
+08), from
+04 to
+23@ retrograde line from
+18@ transition line
+07, from
+03dep
+02*4
+20Value is too large (
+53The equation I just processed has given some variable
+54a value of 4096 or more. Continue and I'll try to cope
+47with that big value; but it might be dangerous.
+47(Set warningcheck:=0 to suppress this message.)
+05####
+03##
+15Bad PREVDEP at
+16Out of order at
+18Redundant equation
+43I already knew that this equation was true.
+50But perhaps no harm has been done; let's continue.
+23[unknown command code!]
+03<*>
+08<insert>
+12<scantokens>
+02l.
+10<forever>
+11<argument>
+16<recently read>
+19<to be read again>
+16<inserted text>
+05<for(
+03)>
+16input stack size
+17text input levels
+08endinput
+47Incomplete if; all text was ignored after line
+51A forbidden `outer' token occurred in skipped text.
+58This kind of error happens when you say `if...' and forget
+57the matching `fi'. I've inserted a `fi'; this might work.
+53The file ended while I was skipping conditional text.
+10File ended
+21Forbidden token found
+16 while scanning
+41I suspect you have forgotten an `enddef',
+52causing me to read past where you wanted me to stop.
+49I'll try to recover; but if the error is serious,
+51you'd better type `E' or `X' now and fix your file.
+27to the end of the statement
+42A previous error seems to have propagated,
+15a text argument
+45It seems that a right delimiter was left out,
+18the definition of
+14the text of a
+05 loop
+41I suspect you have forgotten an `endfor',
+08Runaway
+05text?
+11definition?
+05loop?
+39Text line contains an invalid character
+53A funny symbol that I can't read has just been input.
+48Continue, and I'll forget that it ever happened.
+40Incomplete string token has been flushed
+53Strings should finish on the same line as they began.
+50I've deleted the partial string; you might want to
+48insert another by typing, e.g., `I"new string"'.
+32Enormous number has been reduced
+52I can't handle numbers bigger than about 4095.99998;
+53so I've changed your constant to that maximum amount.
+36(Please type a command or say `end')
+37*** (job aborted, no legal end found)
+02=>
+03def
+06vardef
+10primarydef
+12secondarydef
+11tertiarydef
+03for
+11forsuffixes
+07forever
+05quote
+02#@
+02@#
+31Missing symbolic token inserted
+52Sorry: You can't redefine a number, string, or expr.
+49I've inserted an inaccessible symbol so that your
+60definition will be completed without mixing me up too badly.
+51Sorry: You can't redefine my error-recovery tokens.
+50The next thing in this `def' should have been `=',
+54because I've already looked at the definition heading.
+49But don't worry; I'll pretend that an equals sign
+45was present. Everything from here to `enddef'
+43will be the replacement text of this macro.
+04expr
+06suffix
+04text
+07primary
+09secondary
+08tertiary
+41This variable already starts with a macro
+44After `vardef a' you can't say `vardef a.b'.
+40So I'll have to discard this definition.
+46Missing parameter type; `expr' will be assumed
+52You should've had `expr' or `suffix' or `text' here.
+20parameter stack size
+14Extra `endfor'
+40I'm not currently working on a for loop,
+40so I had better not try to end anything.
+05input
+09Lost loop
+53I'm confused; after exiting from a loop, I still seem
+53to want to repeat it. I'll try to forget the problem.
+22No loop is in progress
+51Why say `exitif' when there's nothing to exit from?
+57After `exitif <boolean exp>' I expect to see a semicolon.
+35I shall pretend that one was there.
+20*** (loop confusion)
+12Not a string
+41I'm going to flush this expression, since
+48scantokens should be followed by a known string.
+03)<-
+22Too many arguments to
+11 Missing `
+52I'm going to assume that the comma I just read was a
+57right delimiter, and then I'll begin expanding the macro.
+55You might want to delete some tokens before continuing.
+20Missing argument to
+48That macro has more parameters than you thought.
+54I'll continue by pretending that each missing argument
+23is either zero or null.
+54I've finished reading a macro argument and am about to
+56read another; the arguments weren't delimited correctly.
+51I've gotten to the end of the macro parameter list.
+05 for
+57I've got the first argument; will look now for the other.
+02if
+04else
+06elseif
+49There should've been a colon after the condition.
+06{true}
+07{false}
+06Extra
+43I'm ignoring this; it doesn't match any if.
+09Improper
+38When you say `for x=a step b until c',
+43the initial value `a' and the step size `b'
+55and the final value `c' must have known numeric values.
+57The next thing in this loop should have been `=' or `:='.
+47was present, and I'll look for the values next.
+51The next thing in this loop should have been a `:'.
+41So I'll pretend that a colon was present;
+50everything from here to `endfor' will be iterated.
+07 ENDFOR
+12{loop value=
+13initial value
+09step size
+47I assume you meant to say `until' after `step'.
+48So I'll look for the final value and colon next.
+11final value
+05.base
+15input file name
+19I can't find file `
+23I can't write on file `
+02'.
+03.mf
+20Please type another
+45*** (job aborted, file error in nonstop mode)
+02:
+05mfput
+04.log
+02**
+20transcript file name
+02
+20file name for output
+37File names can't appear within macros
+46Sorry...I've converted what follows to tokens,
+37possibly garbaging the name you gave.
+51Please delete the tokens and insert the name again.
+03exp
+26 (see the transcript file)
+13 (future pen)
+10linearform
+03>>
+07recycle
+04###
+03 =
+09A primary
+30 expression can't begin with `
+58I'm afraid I need some sort of value in order to continue,
+49so I've tentatively inserted `0'. You may want to
+43delete this zero and insert something else;
+50see Chapter 27 of The METAFONTbook for an example.
+39Nonnumeric ypart has been replaced by 0
+48I thought you were giving me a pair `(x,y)'; but
+50after finding a nice xpart `x' I found a ypart `y'
+54that isn't of numeric type. So I've changed y to zero.
+59(The y that I didn't like appears above the error message.)
+22A group begun on line
+12 never ended
+56I saw a `begingroup' back there that hasn't been matched
+47by `endgroup'. So I've inserted `endgroup' now.
+16Division by zero
+43I'll pretend that you meant to divide by 1.
+44Improper subscript has been replaced by zero
+54A bracketed subscript must have a known numeric value;
+59unfortunately, what I found was the value that appears just
+55above this error message. So I'll try a zero subscript.
+09Variable
+21 has been obliterated
+54It seems you did a nasty thing---probably by accident,
+46but nevertheless you nearly hornswoggled me...
+50While I was evaluating the right-hand side of this
+51command, something happened, and the left-hand side
+52is no longer a variable! So I won't change anything.
+51While I was evaluating the suffix of this variable,
+55something was redefined, and it's no longer a variable!
+59In order to get back on my feet, I've inserted `0' instead.
+04copy
+47I've scanned an expression of the form `a[b,c',
+41so a right bracket should have come next.
+51I've seen a `[' and a subscript value, in a suffix,
+11A secondary
+10A tertiary
+24Pen path must be a cycle
+39I can't make a pen from the given path.
+02An
+49Undefined coordinates have been replaced by (0,0)
+49I need x and y numbers for this part of the path.
+42The value I found (see above) was no good;
+48so I'll try to keep going by using zero instead.
+45(Chapter 27 of The METAFONTbook explains that
+36you might want to type `I ???' now.)
+45Undefined x coordinate has been replaced by 0
+51I need a `known' x value for this part of the path.
+45Undefined y coordinate has been replaced by 0
+51I need a `known' y value for this part of the path.
+49I've scanned a direction spec for part of a path,
+39so a right brace should have come next.
+36Improper curl has been replaced by 1
+43A curl must be a known, nonnegative number.
+46I've got the x coordinate of a path direction;
+36will look for the y coordinate next.
+45A path join command should end with two dots.
+34Improper tension has been set to 1
+53The expression above should have been a number >=3/4.
+46Paths don't touch; `&' will be changed to `..'
+48When you join paths `p&q', the ending point of p
+49must be exactly equal to the starting point of q.
+53So I'm going to pretend that you said `p..q' instead.
+46Undefined condition will be treated as `false'
+53The expression shown above should have had a definite
+48true-or-false value. I'm changing it to `false'.
+40*** (cannot readstring in nonstop modes)
+12unknown pair
+15unknown numeric
+17Not implemented:
+59I'm afraid I don't know how to apply that operation to that
+53particular type. Continue, and I'll simply return the
+54argument (shown above) as the result of the operation.
+02)}
+30String contains illegal digits
+55I zeroed out characters that weren't in the range 0..7.
+48I zeroed out characters that weren't hex digits.
+18Number too large (
+57I have trouble with numbers greater than 4095; watch out.
+58combination of types. Continue, and I'll return the second
+52argument (see above) as the result of the operation.
+02{(
+49The quantities shown above have not been equated.
+60Oh dear. I can't decide if the expression above is positive,
+59negative, or zero. So this comparison test won't be `true'.
+41Unknown relation will be considered false
+03)*(
+58You're trying to divide the quantity shown above the error
+55message by zero. I'm going to divide it by one instead.
+32Improper transformation argument
+46The expression shown above has the wrong type,
+39so I can't transform anything using it.
+37Transform components aren't all known
+56I'm unable to apply a partially specified transformation
+42except to a fully known pair or transform.
+31That transformation is too hard
+49I can apply complicated transformations to paths,
+49but I can only do integer operations on pictures.
+16Too far to shift
+49I can't shift the picture as requested---it would
+30A statement can't begin with `
+51I was looking for the beginning of a new statement.
+58If you just proceed without changing anything, I'll ignore
+56everything up to the next `;'. Please insert a semicolon
+58now in front of anything that you don't want me to delete.
+52(See Chapter 27 of The METAFONTbook for an example.)
+28Extra tokens will be flushed
+59I've just read as much of that statement as I could fathom,
+59so a semicolon should have been next. It's very puzzling...
+53but I'll try to get myself back together, by ignoring
+19Isolated expression
+40I couldn't find an `=' or `:=' after the
+50expression that is shown above this error message,
+44so I guess I'll just ignore it and carry on.
+36Improper `:=' will be changed to `='
+54I didn't find a variable name at the left of the `:=',
+50so I'm going to pretend that you said `=' instead.
+03)=(
+19Internal quantity `
+28' must receive a known value
+56I can't set an internal quantity to anything but a known
+54numeric value, so I'll have to ignore this assignment.
+30Equation cannot be performed (
+58I'm sorry, but I don't know how to make such things equal.
+55(See the two expressions just above the error message.)
+34Redundant or inconsistent equation
+56An equation between already-known quantities can't help.
+50But don't worry; continue and I'll just ignore it.
+21Inconsistent equation
+58The equation I just read contradicts what was said before.
+09 (off by
+48Declared variable conflicts with previous vardef
+56You can't use, e.g., `numeric foo[]' after `vardef foo'.
+51Proceed, and I'll ignore the illegal redeclaration.
+51Illegal suffix of declared variable will be flushed
+50Variables in declarations must consist entirely of
+46names and collective subscripts, e.g., `x[]a'.
+57Are you trying to use a reserved word in a variable name?
+43I'm going to discard the junk I found here,
+51up to the next comma or the end of the declaration.
+49Explicit subscripts like `x15a' aren't permitted.
+16Extra `endgroup'
+44I'm not currently working on a `begingroup',
+03end
+04dump
+46Always say `randomseed:=<numeric expression>'.
+29Unknown value will be ignored
+48Your expression was too random for me to handle,
+43so I won't change the random seed just now.
+13{randomseed:=
+13errorstopmode
+05inner
+05outer
+55I found no right delimiter to match a left one. So I've
+56put one in, behind the scenes; this may fix the problem.
+11The token `
+32' is no longer a right delimiter
+48Strange: This token has lost its former meaning!
+44I'll read it as a right delimiter this time;
+43but watch out, I'll probably miss it later.
+10(%CAPSULE)
+28' isn't an internal quantity
+55Something like `tracingonline' should follow `interim'.
+46You should have said `let symbol = something'.
+55was present. The next token I read will be `something'.
+19number of internals
+09showtoken
+09showstats
+04show
+12showvariable
+16showdependencies
+02>
+08(outer)
+03lef
+04righ
+25t delimiter that matches
+03tag
+08variable
+06macro:
+09'd macro:
+17[repeat the loop]
+13Memory usage
+17 still untouched)
+13String usage
+07=macro:
+02OK
+56This isn't an error message; I'm just showing something.
+07contour
+10doublepath
+04also
+07withpen
+10withweight
+08dropping
+07keeping
+13Improper type
+54Next time say `withweight <known numeric expression>';
+55I'll ignore the bad `with' clause and look for another.
+47Next time say `withpen <known pen expression>';
+40Weight must be -3, -2, -1, +1, +2, or +3
+20 is the wrong type (
+45I was looking for a "known" picture variable.
+37So I'll not change anything just now.
+23Not a suitable variable
+61At this point I needed to see the name of a picture variable.
+58(Or perhaps you have indeed presented me with one; I might
+59have missed it, if it wasn't followed by the proper token.)
+16Improper `addto'
+54This expression should have specified a known picture.
+46This expression should have been a known path.
+11Not a cycle
+58That contour should have ended with `..cycle' or `&cycle'.
+37Strange path (turning number is zero)
+43Backwards path (turning number is negative)
+53The path doesn't have a counterclockwise orientation,
+41so I'll probably have trouble drawing it.
+51(See Chapter 27 of The METAFONTbook for more help.)
+17Bad window number
+42It should be the number of an open window.
+21Improper `openwindow'
+52Say `openwindow k from (r0,c0) to (r1,c1) at (x,y)',
+57where all quantities are known and k is between 0 and 15.
+19Bad culling amounts
+44Always cull by known amounts that exclude 0.
+07message
+10errmessage
+07errhelp
+46A message should be a known string expression.
+32(That was another `errmessage'.)
+51This error message was generated by an `errmessage'
+43command, so I can't give any explicit help.
+51Pretend that you're Miss Marple: Examine all clues,
+41and deduce the truth by inspired guesses.
+09Enormous
+17 has been reduced
+48Font metric dimensions must be less than 2048pt.
+08charlist
+08ligtable
+10extensible
+10headerbyte
+09fontdimen
+35Invalid code has been replaced by 0
+54I was looking for a number between 0 and 255, or for a
+55string of length 1. Didn't find it; will use 0 instead.
+10Character
+02||
+05code
+12 is already
+13in a ligtable
+13in a charlist
+51It's not legal to label a character more than once.
+17Improper location
+43I was looking for a known, positive number.
+50For safety's sake I'll ignore the present command.
+56A colon should follow a headerbyte or fontinfo location.
+21Illegal ligtable step
+38I was looking for `=:' or `kern' here.
+13ligtable size
+02=:
+03=:|
+04=:|>
+03|=:
+04|=:>
+04|=:|
+05|=:|>
+06|=:|>>
+04kern
+15Too far to skip
+57At most 127 lig/kern steps can separate skipto1 from 1::.
+13Improper kern
+51The amount of kern should be a known numeric value.
+39I'm processing `extensible c: t,m,b,r'.
+23Improper font parameter
+06(some
+41 values had to be adjusted by as much as
+03pt)
+47(illegal design size has been changed to 128pt)
+04.tfm
+26file name for font metrics
+24Font metrics written on
+13(local label
+15:: was missing)
+24(a font metric dimension
+23 font metric dimensions
+21 had to be decreased)
+17 METAFONT output
+03.gf
+02gf
+19 (just shipped out)
+51(There's unbounded black in character shipped out!)
+07special
+10numspecial
+21Unsuitable expression
+59The expression shown above has the wrong type to be output.
+06title
+18Output written on
+10 character
+02,
+08 bytes).
+08 (INIMF)
+25 strings of total length
+43 memory locations dumped; current usage is
+16 symbolic tokens
+17 (preloaded base=
+14base file name
+26Beginning to dump on file
+22Transcript written on
+02 )
+19(end occurred when
+09 on line
+16 was incomplete)
+52(see the transcript file for additional information)
+33(dump is performed only by INIMF)
+21debug # (-1 to exit):
+*415546872
diff --git a/systems/knuth/local/mf-sparc/mf_arith.c b/systems/knuth/local/mf-sparc/mf_arith.c
new file mode 100644
index 0000000000..5347107e81
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/mf_arith.c
@@ -0,0 +1,142 @@
+/*
+ * mf_arith.c -- optimized arithmetic routines for UNIX METAFONT 84
+ *
+ * These functions account for a significant percentage of the processing
+ * time used by METAFONT, and have been recoded in assembly language for
+ * some classes of machines.
+ *
+ * As yet I don't have code for SPARC, so I'm just using a C version
+ * by richards, in hopes that cc does better than pc on the brute-force
+ * algorithm found in mf.web.
+ *
+ * function makefraction(p, q: integer): fraction;
+ * { Calculate the function floor( (p * 2^28) / q + 0.5 ) }
+ * { if both p and q are positive. If not, then the value }
+ * { of makefraction is calculated as though both *were* }
+ * { positive, then the result sign adjusted. }
+ * { (e.g. makefraction ALWAYS rounds away from zero) }
+ * { In case of an overflow, return the largest possible }
+ * { value (2^32-1) with the correct sign, and set global }
+ * { variable "aritherror" to 1. Note that -2^32 is }
+ * { considered to be an illegal product for this type of }
+ * { arithmetic! }
+ *
+ * function takefraction(f: fraction; q: integer): integer;
+ * { Calculate the function floor( (p * q) / 2^28 + 0.5 ) }
+ * { takefraction() rounds in a similar manner as }
+ * { makefraction() above. }
+ *
+ */
+
+#include "h00vars.h"
+
+extern bool aritherror; /* to be set on overflow */
+
+#define EL_GORDO 0x7fffffff /* 2^31-1 */
+#define FRACTION_ONE 0x10000000 /* 2^28 */
+#define FRACTION_HALF 0x08000000 /* 2^27 */
+#define FRACTION_FOUR 0x40000000 /* 2^30 */
+
+int makefraction(p, q)
+ register int p, q;
+{
+ int negative;
+ register int be_careful;
+ register int f;
+ int n;
+
+ if (p < 0) {
+ negative = 1;
+ p = -p;
+ } else negative = 0;
+
+ if (q < 0) {
+ negative = !negative;
+ q = -q;
+ }
+
+ n = p / q;
+ p = p % q;
+
+ if (n >= 8) {
+ aritherror = TRUE;
+ return (negative? -EL_GORDO : EL_GORDO);
+ }
+
+ n = (n-1)*FRACTION_ONE;
+ f = 1;
+ do {
+ be_careful = p - q;
+ p = be_careful + p;
+ if (p >= 0) {
+ f = f + f + 1;
+ } else {
+ f <<= 1;
+ p += q;
+ }
+ } while (f < FRACTION_ONE);
+
+ be_careful = p - q;
+ if ((be_careful + p) >= 0)
+ f += 1;
+ return (negative? -(f+n) : (f+n));
+
+}
+
+int takefraction(q, f)
+ register int q;
+ register int f;
+{
+ int n, negative;
+ register int p, be_careful;
+
+ if (f < 0) {
+ negative = 1;
+ f = -f;
+ } else negative = 0;
+ if (q < 0) {
+ negative = !negative;
+ q = -q;
+ }
+ if (f < FRACTION_ONE)
+ n = 0;
+ else {
+ n = f / FRACTION_ONE;
+ f = f % FRACTION_ONE;
+ if (q < (EL_GORDO / n))
+ n = n * q;
+ else {
+ aritherror = TRUE;
+ n = EL_GORDO;
+ }
+ }
+
+ f += FRACTION_ONE;
+ p = FRACTION_HALF;
+ if (q < FRACTION_FOUR)
+ do {
+ if (f & 0x1)
+ p = (p+q) >> 1;
+ else
+ p >>= 1;
+ f >>= 1;
+ } while (f > 1);
+ else
+ do {
+ if (f & 0x1)
+ p = p + ((q-p) >> 1);
+ else
+ p >>= 1;
+ f >>= 1;
+ } while (f > 1);
+
+ be_careful = n - EL_GORDO;
+ if ((be_careful + p) > 0) {
+ aritherror = TRUE;
+ n = EL_GORDO - p;
+ }
+
+ return(negative? -(n+p) : (n+p));
+}
+
+
diff --git a/systems/knuth/local/mf-sparc/mf_sunwin.c b/systems/knuth/local/mf-sparc/mf_sunwin.c
new file mode 100644
index 0000000000..f1e9fa9b39
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/mf_sunwin.c
@@ -0,0 +1,90 @@
+/*
+ * XView interface to MetaFont
+ * (written hastily and without much understanding...)
+ */
+#define SCREENWIDTH 1024 /* must match the constant in inimf.ch */
+#define SCREENDEPTH 800 /* must match the constant in inimf.ch */
+
+#include <stdio.h>
+#include <xview/xview.h>
+#include <xview/canvas.h>
+#include <X11/Xlib.h>
+
+static Frame frame; /* container */
+static Canvas canvas; /* the viewing and imaging area */
+static Xv_Window canvas_paintwin; /* image component of |canvas| */
+static Display *display; /* handle to X server */
+static Visual *screen; /* where the X server paints */
+static Window xcanvas; /* the X11 ``drawable'' component of our canvas */
+static GC gc; /* X graphic context */
+static XGCValues GCvalues; /* changes to a graphic context */
+
+/*
+ * updatescreen; -- make sure screen display is current
+ */
+
+updatescreen()
+{
+ notify_dispatch();
+ XFlush(display);
+}
+
+/*
+ * init_screen: boolean; return true if window operations legal
+ */
+
+initscreen()
+{
+ if (xv_init(NULL)==NULL) return 0;
+ frame=(Frame)xv_create(NULL,FRAME,XV_WIDTH,700,XV_HEIGHT,600,
+ FRAME_SHOW_HEADER,FALSE,
+ XV_SHOW,TRUE,NULL);
+ canvas=(Canvas)xv_create(frame,CANVAS,CANVAS_REPAINT_PROC,updatescreen,
+ CANVAS_X_PAINT_WINDOW,TRUE,
+ XV_HEIGHT,SCREENDEPTH,XV_WIDTH,SCREENWIDTH,
+ CANVAS_AUTO_EXPAND,FALSE,CANVAS_AUTO_SHRINK,FALSE,
+ NULL);
+ canvas_paintwin=(Xv_window)xv_get(canvas,CANVAS_NTH_PAINT_WINDOW,0);
+ xcanvas=(Window)xv_get(canvas_paintwin,XV_XID);
+ display=(Display*)xv_get(frame,XV_DISPLAY);
+ screen=(Visual*)xv_get(frame,XV_VISUAL);
+ gc=XCreateGC(display,DefaultRootWindow(display),0,GCvalues);
+ notify_do_dispatch(); /* this should allow terminal input */
+ return 1;
+}
+
+/*
+ * blankrectangle: reset rectangle bounded by ([left,right],[top,bottom])
+ * to background color
+ */
+
+blankrectangle(left, right, top, bottom)
+ short left, right;
+ short top, bottom;
+{
+ XSetFunction(display,gc,GXclear);
+ XFillRectangle(display,xcanvas,gc,left,top,right-left,bottom-top);
+}
+
+/*
+ * paintrow -- paint row r starting with color b, up to next
+ * transition specified by vector a, switch colors,
+ * and continue for n transitions.
+ */
+
+paintrow(r, b, a, n)
+ short r;
+ short b;
+ short a[];
+ short n;
+{
+ register short *p,*q=&a[n];
+ XSetFunction(display,gc,b?GXset:GXclear);
+ for (p=a;p<q;p+=2)
+ XFillRectangle(display,xcanvas,gc,*p,r,*(p+1)-*p,1);
+ XSetFunction(display,gc,b?GXclear:GXset);
+ for (p=a+1;p<q;p+=2)
+ XFillRectangle(display,xcanvas,gc,*p,r,*(p+1)-*p,1);
+ notify_dispatch(); /* without this, the Notifier queue overflows */
+}
+
diff --git a/systems/knuth/local/mf-sparc/mf_window.h b/systems/knuth/local/mf-sparc/mf_window.h
new file mode 100644
index 0000000000..761cf006c9
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/mf_window.h
@@ -0,0 +1,15 @@
+{ $Header: mf_window.h,v 0.999999 86/01/13 00:43:56 richards Released $ }
+
+{ External procedures for UNIX MetaFont VIRMF for display graphics }
+
+function initscreen: boolean;
+ external;
+
+procedure updatescreen;
+ external;
+
+procedure blankrectangle(leftcol, rightcol: screencol; toprow, botrow: screenrow);
+ external;
+
+procedure paintrow(r: screenrow; b: pixelcolor; var a: transspec; n: screencol);
+ external;
diff --git a/systems/knuth/local/mf-sparc/plain.base b/systems/knuth/local/mf-sparc/plain.base
new file mode 100644
index 0000000000..8aff956dc2
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/plain.base
Binary files differ
diff --git a/systems/knuth/local/mf-sparc/plain.log b/systems/knuth/local/mf-sparc/plain.log
new file mode 100644
index 0000000000..41d972df4f
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/plain.log
@@ -0,0 +1,16 @@
+This is METAFONT, Version 2.7182 for SunOS (INIMF) 8 AUG 1998 21:30
+**plain \input local \dump
+(/home/tex/dist/lib/plain.mf
+Preloading the plain base, version 2.71: preliminaries,
+ basic constants and mathematical macros,
+ macros for converting from device-independent units to pixels,
+ macros and tables for various modes of operation,
+ macros for drawing and filling,
+ macros for proof labels and rules,
+ macros for character and font administration,
+and a few last-minute items.) (/home/tex/local/lib/local.mf)
+Beginning to dump on file plain.base
+ (preloaded base=plain 98.8.8)
+1407 strings of total length 23104
+5273 memory locations dumped; current usage is 1450&3664
+525 symbolic tokens
diff --git a/systems/knuth/local/mf-sparc/trap1.in b/systems/knuth/local/mf-sparc/trap1.in
new file mode 100644
index 0000000000..1e7b96cab3
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/trap1.in
@@ -0,0 +1,3 @@
+
+\input trap
+
diff --git a/systems/knuth/local/mf-sparc/trap2.in b/systems/knuth/local/mf-sparc/trap2.in
new file mode 100644
index 0000000000..d3dba8ac65
--- /dev/null
+++ b/systems/knuth/local/mf-sparc/trap2.in
@@ -0,0 +1 @@
+ &trap trap