DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T U

⟦c7696481f⟧ TextFile

    Length: 75110 (0x12566)
    Types: TextFile
    Notes: Uncompressed file

Derivation

└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦beba6c409⟧ »unix3.0/Unsupported.tar.Z« 
        └─⟦25c524ae4⟧ 
            └─⟦c736f8995⟧ »Unsupported/texlib.sh.Z« 
                └─⟦this⟧ 

TextFile

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#-----cut here-----cut here-----cut here-----cut here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	dvityext.BSD4_n.c
#	dvityext.BSD4_n.h
#	dvityext.SYS_V.c
#	dvityext.SYS_V.h
#	ext.PYR.c
#	ext.SYS_V.c
#	ext.VaxSun.c
#	h00vars.PYR.h
#	h00vars.SUN.h
#	h00vars.SYS_V.h
#	h00vars.VAX.h
#	pltotfext.SYS_V.c
#	pltotfext.SYS_V.h
#	tangext.BSD4_n.c
#	tangext.BSD4_n.h
#	tangext.SYS_V.c
#	tangext.SYS_V.h
#	tftoplext.SYS_V.c
#	tftoplext.SYS_V.h
#	weavext.BSD4_n.c
#	weavext.SYS_V.c
# This archive created: Sat Jul  2 22:28:04 1988
cat << \SHAR_EOF > dvityext.BSD4_n.c
/* External procedures for dvitype				*/
/*   Written by: H. Trickey, 2/19/83 (adapted from TeX's ext.c) */

#include "texpaths.h"		/* defines default TEXFONTS path */
#include "h00vars.h"		/* defines Pascal I/O structure */

char *fontpath;

char *getenv();

/*
 * setpaths is called to set up the pointer fontpath
 * as follows:  if the user's environment has a value for TEXFONTS
 * then use it;  otherwise, use defaultfontpath.
 */
setpaths()
{
	register char *envpath;
	
	if ((envpath = getenv("TEXFONTS")) != NULL)
	    fontpath = envpath;
	else
	    fontpath = defaultfontpath;
}

#define namelength 100   /* should agree with dvitype.ch */
extern char curname[],realnameoffile[]; /* these have size namelength */

/*
 *	testaccess(amode,filepath)
 *
 *  Test whether or not the file whose name is in the global curname
 *  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 curname 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 FONTFILEPATH 3

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 FONTFILEPATH: curpathplace = fontpath; break;
	}
    if (curname[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[namelength]))
	    *p++ = ' ';
	}
    return (ok);
}

/*
 * packrealnameoffile(cpp) makes realnameoffile contain the directory at *cpp,
 * followed by '/', followed by the characters in curname 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 curname 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[namelength-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 curname to realname... */
    p = curname;
    while (*p != ' ') {
	if (realname >= &(realnameoffile[namelength-1])) {
	    fprintf(stderr,"! Full file name is too long\n");
	    break;
	    }
	*realname++ = *p++;
	}
    *realname = '\0';
}
SHAR_EOF
cat << \SHAR_EOF > dvityext.BSD4_n.h
procedure setpaths;
    external;

function testaccess(accessmode:integer; filepath:integer): boolean;
    external;
SHAR_EOF
cat << \SHAR_EOF > dvityext.SYS_V.c
/* External procedures for dvitype				*/
/*   Written by: H. Trickey, 2/19/83 (adapted from TeX's ext.c) */

#include "texpaths.h"		/* defines default TEXFONTS path */
#include "h00vars.h"		/* defines Pascal I/O structure */

char *fontpath;

char *getenv();

/*
 * setpaths is called to set up the pointer fontpath
 * as follows:  if the user's environment has a value for TEXFONTS
 * then use it;  otherwise, use defaultfontpath.
 */
setpaths()
{
	register char *envpath;
	
	if ((envpath = getenv("TEXFONTS")) != NULL)
	    fontpath = envpath;
	else
	    fontpath = defaultfontpath;
}

#define namelength 100   /* should agree with dvitype.ch */
extern char curname[],realnameoffile[]; /* these have size namelength */

/*
 *	testaccess(amode,filepath)
 *
 *  Test whether or not the file whose name is in the global curname
 *  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 curname 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 FONTFILEPATH 3

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 FONTFILEPATH: curpathplace = fontpath; break;
	}
    if (curname[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[namelength]))
	    *p++ = ' ';
	}
    return (ok);
}

/*
 * packrealnameoffile(cpp) makes realnameoffile contain the directory at *cpp,
 * followed by '/', followed by the characters in curname 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 curname 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[namelength-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 curname to realname... */
    p = curname;
    while (*p != ' ') {
	if (realname >= &(realnameoffile[namelength-1])) {
	    fprintf(stderr,"! Full file name is too long\n");
	    break;
	    }
	*realname++ = *p++;
	}
    *realname = '\0';
}

flush(filep)
	register struct iorec	*filep;
{
	if (filep->funit & FWRITE)
		fflush(filep->fbuf);
}
SHAR_EOF
cat << \SHAR_EOF > dvityext.SYS_V.h
procedure setpaths;
    external C;

function testaccess(accessmode:integer; filepath:integer): boolean;
    external C;

procedure flush(var f: text); external C;
SHAR_EOF
cat << \SHAR_EOF > ext.PYR.c
/* external procedures called by TeX */
#include <signal.h>
#include <time.h>
#include "texpaths.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);
	return(0);
}

closeb(f)
	int *f; /* actually, file pointer, but it doesn't matter */
{
	close1(f);
	return(0);
}

closew(f)
	int *f; /* actually, file pointer, but it doesn't matter */
{
	close1(f);
	return(0);
}

/* conversion functions */

double
tofloat(x)
long x;
{
	/* really, we were passed a float, but C's idea of a
	   float parameter is 8 bytes, so do a bit of trickery */
	return((double) *((float *) &x));
}

long
unfloat(x)
double x;
{
        float  y = x;
        
        return(* ((long *) &y));
}

extern int interrupt;	/* To be made nonzero to tell TeX 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);
	return(0);
}

/*
**      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);
	return(0);
}


/* fixed arrays are used to hold the paths, to avoid any possible problems
   involving interaction of malloc and undump		*/

char inputpath[MAXINPATHCHARS] = defaultinputpath;
char fontpath[MAXOTHPATHCHARS] = defaultfontpath;
char formatpath[MAXOTHPATHCHARS] = defaultformatpath;
char poolpath[MAXOTHPATHCHARS] = defaultpoolpath;

char *getenv();

/*
 * setpaths is called to set up the arrays inputpath, fontpath, formatpath
 * 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 TeX 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 TeX).
 */
setpaths()
{
	register char *envpath;
	
	if ((envpath = getenv("TEXINPUTS")) != NULL)
	    copypath(inputpath,envpath,MAXINPATHCHARS);
	if ((envpath = getenv("TEXFONTS")) != NULL)
	    copypath(fontpath,envpath,MAXOTHPATHCHARS);
	if ((envpath = getenv("TEXFORMATS")) != NULL)
	    copypath(formatpath,envpath,MAXOTHPATHCHARS);
	if ((envpath = getenv("TEXPOOL")) != NULL)
	    copypath(poolpath,envpath,MAXOTHPATHCHARS);
	return(0);
}

/*
 * copypath(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.
 */
copypath(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 */
		}
	return(0);
}

extern int buffer[],xord[]; 
extern int 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 int *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 */
	int *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;
	return(0);
}

#define filenamesize 1024   /* should agree with initex.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 FONTFILEPATH 3
#define FORMATFILEPATH 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 FONTFILEPATH: curpathplace = fontpath; break;
	case FORMATFILEPATH: curpathplace = formatpath; 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';
	return(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);
			}
		}
}


/*
**	writedvi(a,b)
**
**  writedvi is called to write dvibuf[a..b] to dvifile
**  Unfortunately, dvibuf 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 dvifile;
extern int dvibuf[];
writedvi (a,b)
	int a,b;
{
	register int *ptr,*final;
	register FILE *iop;
	
	iop=dvifile.fbuf;
	ptr= &(dvibuf[a]);
	final= &(dvibuf[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)
**
**  TeX82 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 "/usr/ucb/vi". If you want a different
**  editor, create a shell environment variable TEXEDIT 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 TEXEDIT string for a
**  variant copy of "vi" might be:
**  
**	setenv TEXEDIT "/usr/local/bin/vi +%d %s"
**  
*/

   char dvalue[] = "/usr/ucb/vi +%d %s";
   char *texeditvalue = &dvalue[0];

   calledit(filename, fnlength, linenumber)
      int *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("TEXEDIT")))
	 texeditvalue = temp;

      /* Make command string containing envvalue, filename, and linenumber */
      if (NULL ==
	 (command = (char *) malloc(strlen(texeditvalue) + fnlength + 25))) {
	 fprintf(stderr, "! Not enough memory to issue editor command\n");
	 exit(1);
	 }
      temp = command;
      while ((c = *texeditvalue++) != '\0') {
	 if (c == '%') {
	    switch (c = *texeditvalue++) {
	       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++ = (char)filename[i++];
		  sdone = 1;
		  break;
	       case '\0':
		  *temp++ = '%';
		  texeditvalue--; /* 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 TeX had found an error before you typed "e". */
      exit(1);
      }
SHAR_EOF
cat << \SHAR_EOF > ext.SYS_V.c
/* external procedures called by TeX */
#include <sys/signal.h>
#include <time.h>
#include "texpaths.h" /* defines MAXINPATHCHARS, defaultinputpath, etc. */
#include "h00vars.h"

/* The following are for closing files */

closea(filep)
	struct iorec *filep;
{
	if (filep->fbuf)
		CLOSE(filep);
}

closeb(filep)
	struct iorec *filep;
{
	if (filep->fbuf)
		CLOSE(filep);
}

closew(filep)
	struct iorec *filep;
{
	if (filep->fbuf)
		CLOSE(filep);
}

/* conversion functions */

double
tofloat(x)
long x;
{
	/* really, we were passed a float, but C's idea of a
	   float parameter is 8 bytes, so do a bit of trickery */
	return((double) *((float *) &x));
}

long
unfloat(x)
double x;
{
        float  y = x;
        
        return(* ((long *) &y));
}

extern int interrupt;	/* To be made nonzero to tell TeX 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 fontpath[MAXOTHPATHCHARS] = defaultfontpath;
char formatpath[MAXOTHPATHCHARS] = defaultformatpath;
char poolpath[MAXOTHPATHCHARS] = defaultpoolpath;

char *getenv();

/*
 * setpaths is called to set up the arrays inputpath, fontpath, formatpath
 * 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 TeX 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 TeX).
 */
setpaths()
{
	register char *envpath;
	
	if ((envpath = getenv("TEXINPUTS")) != NULL)
	    copypath(inputpath,envpath,MAXINPATHCHARS);
	if ((envpath = getenv("TEXFONTS")) != NULL)
	    copypath(fontpath,envpath,MAXOTHPATHCHARS);
	if ((envpath = getenv("TEXFORMATS")) != NULL)
	    copypath(formatpath,envpath,MAXOTHPATHCHARS);
	if ((envpath = getenv("TEXPOOL")) != NULL)
	    copypath(poolpath,envpath,MAXOTHPATHCHARS);
}

/*
 * copypath(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.
 */
copypath(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 char 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 char *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 */
	char *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 initex.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 FONTFILEPATH 3
#define FORMATFILEPATH 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 FONTFILEPATH: curpathplace = fontpath; break;
	case FORMATFILEPATH: curpathplace = formatpath; 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);
			}
		}
}


/*
**	writedvi(a,b)
**
**  writedvi is called to write dvibuf[a..b] to dvifile
**  Unfortunately, dvibuf 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 dvifile;
extern short dvibuf[];
writedvi (a,b)
	int a,b;
{
	register short *ptr,*final;
	register FILE *iop;
	
	iop=dvifile.fbuf;
	ptr= &(dvibuf[a]);
	final= &(dvibuf[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.
	 */
}


/*
**  The following procedure is due to sjc@s1-c.
**
**	calledit(filename, fnlength, linenumber)
**
**  TeX82 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 "/usr/ucb/vi". If you want a different
**  editor, create a shell environment variable TEXEDIT 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 TEXEDIT string for a
**  variant copy of "vi" might be:
**  
**	setenv TEXEDIT "/usr/local/bin/vi +%d %s"
**  
*/

   char dvalue[] = "/usr/bin/vi +%d %s";
   char *texeditvalue = &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("TEXEDIT")))
	 texeditvalue = temp;

      /* Make command string containing envvalue, filename, and linenumber */
      if (NULL ==
	 (command = (char *) malloc(strlen(texeditvalue) + fnlength + 25))) {
	 fprintf(stderr, "! Not enough memory to issue editor command\n");
	 exit(1);
	 }
      temp = command;
      while ((c = *texeditvalue++) != '\0') {
	 if (c == '%') {
	    switch (c = *texeditvalue++) {
	       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++];
		  sdone = 1;
		  break;
	       case '\0':
		  *temp++ = '%';
		  texeditvalue--; /* 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 TeX had found an error before you typed "e". */
      exit(1);
      }

flush(filep)
	register struct iorec	*filep;
{
	if (filep->funit & FWRITE)
		fflush(filep->fbuf);
}
SHAR_EOF
cat << \SHAR_EOF > ext.VaxSun.c
/* external procedures called by TeX */
#include <sys/signal.h>
#include <sys/time.h>
#include "texpaths.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);
}

/* conversion functions */

double
tofloat(x)
long x;
{
	/* really, we were passed a float, but C's idea of a
	   float parameter is 8 bytes, so do a bit of trickery */
	return((double) *((float *) &x));
}

long
unfloat(x)
double x;
{
        float  y = x;
        
        return(* ((long *) &y));
}

extern int interrupt;	/* To be made nonzero to tell TeX 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 fontpath[MAXOTHPATHCHARS] = defaultfontpath;
char formatpath[MAXOTHPATHCHARS] = defaultformatpath;
char poolpath[MAXOTHPATHCHARS] = defaultpoolpath;

char *getenv();

/*
 * setpaths is called to set up the arrays inputpath, fontpath, formatpath
 * 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 TeX 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 TeX).
 */
setpaths()
{
	register char *envpath;
	
	if ((envpath = getenv("TEXINPUTS")) != NULL)
	    copypath(inputpath,envpath,MAXINPATHCHARS);
	if ((envpath = getenv("TEXFONTS")) != NULL)
	    copypath(fontpath,envpath,MAXOTHPATHCHARS);
	if ((envpath = getenv("TEXFORMATS")) != NULL)
	    copypath(formatpath,envpath,MAXOTHPATHCHARS);
	if ((envpath = getenv("TEXPOOL")) != NULL)
	    copypath(poolpath,envpath,MAXOTHPATHCHARS);
}

/*
 * copypath(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.
 */
copypath(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 char 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 char *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 */
	char *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 initex.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 FONTFILEPATH 3
#define FORMATFILEPATH 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 FONTFILEPATH: curpathplace = fontpath; break;
	case FORMATFILEPATH: curpathplace = formatpath; 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);
			}
		}
}


/*
**	writedvi(a,b)
**
**  writedvi is called to write dvibuf[a..b] to dvifile
**  Unfortunately, dvibuf 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 dvifile;
extern short dvibuf[];
writedvi (a,b)
	int a,b;
{
	register short *ptr,*final;
	register FILE *iop;
	
	iop=dvifile.fbuf;
	ptr= &(dvibuf[a]);
	final= &(dvibuf[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)
**
**  TeX82 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 "/usr/ucb/vi". If you want a different
**  editor, create a shell environment variable TEXEDIT 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 TEXEDIT string for a
**  variant copy of "vi" might be:
**  
**	setenv TEXEDIT "/usr/local/bin/vi +%d %s"
**  
*/

   char dvalue[] = "/usr/ucb/vi +%d %s";
   char *texeditvalue = &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("TEXEDIT")))
	 texeditvalue = temp;

      /* Make command string containing envvalue, filename, and linenumber */
      if (NULL ==
	 (command = (char *) malloc(strlen(texeditvalue) + fnlength + 25))) {
	 fprintf(stderr, "! Not enough memory to issue editor command\n");
	 exit(1);
	 }
      temp = command;
      while ((c = *texeditvalue++) != '\0') {
	 if (c == '%') {
	    switch (c = *texeditvalue++) {
	       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++];
		  sdone = 1;
		  break;
	       case '\0':
		  *temp++ = '%';
		  texeditvalue--; /* 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 TeX had found an error before you typed "e". */
      exit(1);
      }
SHAR_EOF
cat << \SHAR_EOF > h00vars.PYR.h
/* Copyright (c) 1979 Regents of the University of California */

/* sccsid[] = "@(#)h00vars.h 1.10 1/10/83"; */

#include <stdio.h>
#include "whoami.h"

#define PXPFILE		"pmon.out"
#define	BITSPERBYTE	8
#define	BITSPERLONG	(BITSPERBYTE * sizeof(long))
#define LG2BITSBYTE	03
#define MSKBITSBYTE	07
#define LG2BITSLONG	05
#define MSKBITSLONG	037
#define HZ		60
#define	MAXLVL		20
#define MAXERRS		75
#define NAMSIZ		76
#define MAXFILES	32
#define PREDEF		2
#define STDLVL	((struct iorec *)(0xc00cc001))
#define GLVL	((struct iorec *)(0xc00cc000))
#define FILNIL		((struct iorec *)(0))
#define INPUT		((struct iorec *)(&input))
#define OUTPUT		((struct iorec *)(&output))
#define ERR		((struct iorec *)(&_err))
typedef enum {FALSE, TRUE} bool;

/*
 * runtime display structure
 */
struct display {
	char	*ap;
	char	*fp;
};

/*
 * formal routine structure
 */
struct formalrtn {
	long		(*fentryaddr)();	/* formal entry point */
	long		fbn;			/* block number of function */
	struct display	fdisp[ MAXLVL ];	/* saved at first passing */
};

/*
 * program variables
 */
extern struct display	_disply[MAXLVL];/* runtime display */
extern int		_argc;		/* number of passed args */
extern char		**_argv;	/* values of passed args */
extern long		_stlim;		/* statement limit */
extern long		_stcnt;		/* statement count */
extern long		_seed;		/* random number seed */
extern char		*_maxptr;	/* maximum valid pointer */
extern char		*_minptr;	/* minimum valid pointer */
extern long		_pcpcount[];	/* pxp buffer */

/*
 * file structures
 */
struct iorechd {
	char		*fileptr;	/* ptr to file window */
	long		lcount;		/* number of lines printed */
	long		llimit;		/* maximum number of text lines */
	FILE		*fbuf;		/* FILE ptr */
	struct iorec	*fchain;	/* chain to next file */
	struct iorec	*flev;		/* ptr to associated file variable */
	char		*pfname;	/* ptr to name of file */
	short		funit;		/* file status flags */
	unsigned short	fblk;		/* index into active file table */
	long		fsize;		/* size of elements in the file */
	char		fname[NAMSIZ];	/* name of associated UNIX file */
};

struct iorec {
	char		*fileptr;	/* ptr to file window */
	long		lcount;		/* number of lines printed */
	long		llimit;		/* maximum number of text lines */
	FILE		*fbuf;		/* FILE ptr */
	struct iorec	*fchain;	/* chain to next file */
	struct iorec	*flev;		/* ptr to associated file variable */
	char		*pfname;	/* ptr to name of file */
	short		funit;		/* file status flags */
	unsigned short	fblk;		/* index into active file table */
	long		fsize;		/* size of elements in the file */
	char		fname[NAMSIZ];	/* name of associated UNIX file */
	char		buf[BUFSIZ];	/* I/O buffer */
	char		window[1];	/* file window element */
};

/*
 * unit flags
 */
#define SPEOLN	0x100	/* 1 => pseudo EOLN char read at EOF */
#define	FDEF	0x080	/* 1 => reserved file name */
#define	FTEXT	0x040	/* 1 => text file, process EOLN */
#define	FWRITE	0x020	/* 1 => open for writing */
#define	FREAD	0x010	/* 1 => open for reading */
#define	TEMP	0x008	/* 1 => temporary file */
#define	SYNC	0x004	/* 1 => window is out of sync */
#define	EOLN	0x002	/* 1 => at end of line */
#define	EOFF	0x001	/* 1 => at end of file */

/*
 * file routines
 */
extern struct iorec	*GETNAME();
extern char		*MKTEMP();
extern char		*PALLOC();

/*
 * file record variables
 */
extern struct iorechd	_fchain;	/* head of active file chain */
extern struct iorec	*_actfile[];	/* table of active files */
extern long		_filefre;	/* last used entry in _actfile */

/*
 * standard files
 */
extern struct iorechd	input;
extern struct iorechd	output;
extern struct iorechd	_err;

/*
 * seek pointer struct for TELL, SEEK extensions
 */
struct seekptr {
	long	cnt;
};
SHAR_EOF
cat << \SHAR_EOF > h00vars.SUN.h
/* Copyright (c) 1979 Regents of the University of California */

/* sccsid[] = "@(#)h00vars.h 1.11 5/8/84"; */
/* THIS VERSION COMES BACK FROM SUN AND ALLEGEDLY MATCH OUR CURRENT
   COMPILER         8/4/84    */

#include <stdio.h>
#include "whoami.h"

#define PXPFILE		"pmon.out"
#define	BITSPERBYTE	8
#define	BITSPERLONG	(BITSPERBYTE * sizeof(long))
#define LG2BITSBYTE	03
#define MSKBITSBYTE	07
#define LG2BITSLONG	05
#define MSKBITSLONG	037
#define HZ		60
#define	MAXLVL		20
#define MAXERRS		75
#define NAMSIZ		76
#define MAXFILES	32
#define PREDEF		2
#ifdef ADDR32
#define STDLVL		((struct iorec *)(0x7ffffff1))
#define GLVL		((struct iorec *)(0x7ffffff0))
#endif ADDR32
#ifdef ADDR16
#define STDLVL		((struct iorec *)(0xfff1))
#define GLVL		((struct iorec *)(0xfff0))
#endif ADDR16
#define FILNIL		((struct iorec *)(0))
#define INPUT		((struct iorec *)(&input))
#define OUTPUT		((struct iorec *)(&output))
#define ERR		((struct iorec *)(&_err))
typedef enum {FALSE, TRUE} bool;
#define	MAXINT		2147483647
#define	MININT		-2147483648


/*
 * runtime display structure
 */
struct display {
	char	*ap;
	char	*fp;
};

/*
 * formal routine structure
 */
struct formalrtn {
	long		(*fentryaddr)();	/* formal entry point */
	long		fbn;			/* block number of function */
	struct display	fdisp[ MAXLVL ];	/* saved at first passing */
};

/*
 * program variables
 */
extern struct display	_disply[MAXLVL];/* runtime display */
extern int		_argc;		/* number of passed args */
extern char		**_argv;	/* values of passed args */
extern long		_stlim;		/* statement limit */
extern long		_stcnt;		/* statement count */
extern long		_seed;		/* random number seed */
extern char		*_maxptr;	/* maximum valid pointer */
extern char		*_minptr;	/* minimum valid pointer */
extern long		_pcpcount[];	/* pxp buffer */

/*
 * file structures
 */
struct iorechd {
	char		*fileptr;	/* ptr to file window */
	long		lcount;		/* number of lines printed */
	long		llimit;		/* maximum number of text lines */
	FILE		*fbuf;		/* FILE ptr */
	struct iorec	*fchain;	/* chain to next file */
	struct iorec	*flev;		/* ptr to associated file variable */
	char		*pfname;	/* ptr to name of file */
	short		funit;		/* file status flags */
	unsigned short	fblk;		/* index into active file table */
	long		fsize;		/* size of elements in the file */
	char		fname[NAMSIZ];	/* name of associated UNIX file */
};

struct iorec {
	char		*fileptr;	/* ptr to file window */
	long		lcount;		/* number of lines printed */
	long		llimit;		/* maximum number of text lines */
	FILE		*fbuf;		/* FILE ptr */
	struct iorec	*fchain;	/* chain to next file */
	struct iorec	*flev;		/* ptr to associated file variable */
	char		*pfname;	/* ptr to name of file */
	short		funit;		/* file status flags */
	unsigned short	fblk;		/* index into active file table */
	long		fsize;		/* size of elements in the file */
	char		fname[NAMSIZ];	/* name of associated UNIX file */
	char		buf[BUFSIZ];	/* I/O buffer */
	char		window[1];	/* file window element */
};

/*
 * unit flags
 */
#define SPEOLN	0x100	/* 1 => pseudo EOLN char read at EOF */
#define	FDEF	0x080	/* 1 => reserved file name */
#define	FTEXT	0x040	/* 1 => text file, process EOLN */
#define	FWRITE	0x020	/* 1 => open for writing */
#define	FREAD	0x010	/* 1 => open for reading */
#define	TEMP	0x008	/* 1 => temporary file */
#define	SYNC	0x004	/* 1 => window is out of sync */
#define	EOLN	0x002	/* 1 => at end of line */
#define	EOFF	0x001	/* 1 => at end of file */

/*
 * file routines
 */
extern struct iorec	*GETNAME();
extern char		*MKTEMP();
extern char		*PALLOC();

/*
 * file record variables
 */
extern struct iorechd	_fchain;	/* head of active file chain */
extern struct iorec	*_actfile[];	/* table of active files */
extern long		_filefre;	/* last used entry in _actfile */

/*
 * standard files
 */
extern struct iorechd	input;
extern struct iorechd	output;
extern struct iorechd	_err;

/*
 * seek pointer struct for TELL, SEEK extensions
 */
struct seekptr {
	long	cnt;
};
SHAR_EOF
cat << \SHAR_EOF > h00vars.SYS_V.h
/*
 * decompiled version (I hope) of important parameters from
 * iorec structure for UNIX System V Pascal
 */

#include <stdio.h>

typedef enum {FALSE, TRUE} bool;

#define MAXFILES	32
#define NAMSIZ		76

struct iorec {
	char		*fileptr;	/* ptr to file window */
	FILE		*fbuf;		/* FILE ptr */
	struct iorec	*fchain;	/* chain to next file */
	struct iorec	*flev;		/* ptr to associated file variable */
	short		funit;		/* file status flags */
	unsigned short	fblk;		/* index into active file table */
	long		fsize;		/* size of elements in the file */
	char		*pfname;	/* ptr to name of file */
	char		fname[NAMSIZ];	/* name of associated UNIX file */
	char		buf[BUFSIZ];	/* I/O buffer */
	char		window[1];	/* file window element */
	long		llimit;		/* maximum number of text lines */
	long		lcount;		/* number of lines printed */
};

#define SPEOLN	0x100	/* 1 => pseudo EOLN char read at EOF */
#define	FDEF	0x080	/* 1 => reserved file name */
#define	FTEXT	0x040	/* 1 => text file, process EOLN */

#define	FWRITE	0x020	/* 1 => open for writing */
#define	FREAD	0x010	/* 1 => open for reading */

#define	TEMP	0x008	/* 1 => temporary file */
#define	SYNC	0x004	/* 1 => window is out of sync */
#define	EOLN	0x002	/* 1 => at end of line */
#define	EOFF	0x001	/* 1 => at end of file */
SHAR_EOF
cat << \SHAR_EOF > h00vars.VAX.h
/* Copyright (c) 1979 Regents of the University of California */

/* sccsid[] = "@(#)h00vars.h 1.10 1/10/83"; */

#include <stdio.h>
#include "whoami.h"

#define PXPFILE		"pmon.out"
#define	BITSPERBYTE	8
#define	BITSPERLONG	(BITSPERBYTE * sizeof(long))
#define LG2BITSBYTE	03
#define MSKBITSBYTE	07
#define LG2BITSLONG	05
#define MSKBITSLONG	037
#define HZ		60
#define	MAXLVL		20
#define MAXERRS		75
#define NAMSIZ		76
#define MAXFILES	32
#define PREDEF		2
#ifdef ADDR32
#define STDLVL		((struct iorec *)(0x7ffffff1))
#define GLVL		((struct iorec *)(0x7ffffff0))
#endif ADDR32
#ifdef ADDR16
#define STDLVL		((struct iorec *)(0xfff1))
#define GLVL		((struct iorec *)(0xfff0))
#endif ADDR16
#define FILNIL		((struct iorec *)(0))
#define INPUT		((struct iorec *)(&input))
#define OUTPUT		((struct iorec *)(&output))
#define ERR		((struct iorec *)(&_err))
typedef enum {FALSE, TRUE} bool;

/*
 * runtime display structure
 */
struct display {
	char	*ap;
	char	*fp;
};

/*
 * formal routine structure
 */
struct formalrtn {
	long		(*fentryaddr)();	/* formal entry point */
	long		fbn;			/* block number of function */
	struct display	fdisp[ MAXLVL ];	/* saved at first passing */
};

/*
 * program variables
 */
extern struct display	_disply[MAXLVL];/* runtime display */
extern int		_argc;		/* number of passed args */
extern char		**_argv;	/* values of passed args */
extern long		_stlim;		/* statement limit */
extern long		_stcnt;		/* statement count */
extern long		_seed;		/* random number seed */
extern char		*_maxptr;	/* maximum valid pointer */
extern char		*_minptr;	/* minimum valid pointer */
extern long		_pcpcount[];	/* pxp buffer */

/*
 * file structures
 */
struct iorechd {
	char		*fileptr;	/* ptr to file window */
	long		lcount;		/* number of lines printed */
	long		llimit;		/* maximum number of text lines */
	FILE		*fbuf;		/* FILE ptr */
	struct iorec	*fchain;	/* chain to next file */
	struct iorec	*flev;		/* ptr to associated file variable */
	char		*pfname;	/* ptr to name of file */
	short		funit;		/* file status flags */
	unsigned short	fblk;		/* index into active file table */
	long		fsize;		/* size of elements in the file */
	char		fname[NAMSIZ];	/* name of associated UNIX file */
};

struct iorec {
	char		*fileptr;	/* ptr to file window */
	long		lcount;		/* number of lines printed */
	long		llimit;		/* maximum number of text lines */
	FILE		*fbuf;		/* FILE ptr */
	struct iorec	*fchain;	/* chain to next file */
	struct iorec	*flev;		/* ptr to associated file variable */
	char		*pfname;	/* ptr to name of file */
	short		funit;		/* file status flags */
	unsigned short	fblk;		/* index into active file table */
	long		fsize;		/* size of elements in the file */
	char		fname[NAMSIZ];	/* name of associated UNIX file */
	char		buf[BUFSIZ];	/* I/O buffer */
	char		window[1];	/* file window element */
};

/*
 * unit flags
 */
#define SPEOLN	0x100	/* 1 => pseudo EOLN char read at EOF */
#define	FDEF	0x080	/* 1 => reserved file name */
#define	FTEXT	0x040	/* 1 => text file, process EOLN */
#define	FWRITE	0x020	/* 1 => open for writing */
#define	FREAD	0x010	/* 1 => open for reading */
#define	TEMP	0x008	/* 1 => temporary file */
#define	SYNC	0x004	/* 1 => window is out of sync */
#define	EOLN	0x002	/* 1 => at end of line */
#define	EOFF	0x001	/* 1 => at end of file */

/*
 * file routines
 */
extern struct iorec	*GETNAME();
extern char		*MKTEMP();
extern char		*PALLOC();

/*
 * file record variables
 */
extern struct iorechd	_fchain;	/* head of active file chain */
extern struct iorec	*_actfile[];	/* table of active files */
extern long		_filefre;	/* last used entry in _actfile */

/*
 * standard files
 */
extern struct iorechd	input;
extern struct iorechd	output;
extern struct iorechd	_err;

/*
 * seek pointer struct for TELL, SEEK extensions
 */
struct seekptr {
	long	cnt;
};
SHAR_EOF
cat << \SHAR_EOF > pltotfext.SYS_V.c
#include "h00vars.h"

bytewrite(curfile, i)
	register struct iorec	*curfile;
	short i;
{
	if (curfile->funit & FREAD) {
		ERROR("%s: Attempt to write, but open for reading\n",
			curfile->fname);
		return;
	}
	putc(i, curfile->fbuf);
	if (ferror(curfile->fbuf)) {
		PERROR("Could not write to ", curfile->fname);
		return;
	}
}
SHAR_EOF
cat << \SHAR_EOF > pltotfext.SYS_V.h
procedure bytewrite(var f: bytefile; i: byte); external C;
SHAR_EOF
cat << \SHAR_EOF > tangext.BSD4_n.c
/* External procedures for tangle/weave */
/*   Written by: H. Trickey, 11/17/83   */

/* Note: these procedures aren't necessary; the default input_ln and
 * flush_buffer routines in tangle/weave work fine on UNIX.
 * However a very big time improvement is acheived by using these.
 */

#define BUF_SIZE 100		/* should agree with tangle.web */

#include "h00vars.h"		/* defines Pascal I/O structure */

extern char buffer[];		/* 0..BUF_SIZE.  Input goes here */
extern char outbuf[];		/* 0..OUT_BUF_SIZE. Output from here */
extern char xord[], xchr[];	/* character translation arrays */
extern char limit;		/* index into buffer, defined in the range
				   0..BUF_SIZE (and note that this is a
				   char rather than a short because BUF_SIZE
				   is 100) */

/*
 * lineread reads from the Pascal text file with iorec pointer filep
 * into buffer[0], buffer[1],..., buffer[limit-1] (and
 * setting "limit").
 * Characters are read until a newline is found (which isn't put in the
 * buffer) or until the next character would go into buffer[BUF_SIZE].
 * And trailing blanks are to be ignored, so limit is really set to
 * one past the last non-blank.
 * 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)
	struct iorec	*filep;
{
	register int	c;
	register char	*cs;	/* pointer into buffer where next char goes */
	register char	*cnb;	/* last non-blank character input */
	register FILE	*iop;	/* stdio-style FILE pointer */
	register int	l;	/* how many chars before buffer overflow */

	iop = filep->fbuf;
	cnb = cs = &buffer[0];
	l = BUF_SIZE;

	/* overflow when next char would go into buffer[BUF_SIZE] */
	while ((--l >= 0) && ((c = getc(iop)) != EOF) && (c != '\n')) {
		if ((*cs++ = xord[c]) != ' ')
			cnb = cs;
	}

	if (c == EOF)
		filep->funit |= EOFF;	/* we hit end-of-file */

	limit = cnb - &buffer[0];
}

/*
 * linewrite writes to the Pascal text file with iorec pointer filep
 * from outbuf[0], outbuf[1],..., outbuf[cnt-1].
 * Translation is done, so that xchr[c] is output instead of c.
 */
linewrite(filep, cnt)
	struct iorec	*filep;
	int		cnt;
{
	register FILE	*iop;	/* stdio-style FILE pointer */
	register char	*cs;	/* pointer to next character to output */
	register int	l;	/* how many characters left to output */

	iop = filep->fbuf;
	cs = &outbuf[0];
	l = cnt;

	while (--l >= 0)
		putc(xchr[*cs++], iop);
}

/*
 *	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);
			}
		}
}
SHAR_EOF
cat << \SHAR_EOF > tangext.BSD4_n.h
procedure exit(x : integer);
 external;
procedure lineread(var f:textfile);
 external;
procedure linewrite(var f:textfile; cnt:integer);
 external;
function testeof(var f:textfile):boolean;
 external;
SHAR_EOF
cat << \SHAR_EOF > tangext.SYS_V.c
/* External procedures for tangle/weave */
/*   Written by: H. Trickey, 11/17/83   */

/* Note: these procedures aren't necessary; the default input_ln and
 * flush_buffer routines in tangle/weave work fine on UNIX.
 * However a very big time improvement is acheived by using these.
 */

#define BUF_SIZE 100		/* should agree with tangle.web */

#include "h00vars.h"		/* defines Pascal I/O structure */

extern char buffer[];		/* 0..BUF_SIZE.  Input goes here */
extern char outbuf[];		/* 0..OUT_BUF_SIZE. Output from here */
extern char xord[], xchr[];	/* character translation arrays */
extern char limit;		/* index into buffer, defined in the range
				   0..BUF_SIZE (and note that this is a
				   char rather than a short because BUF_SIZE
				   is 100) */

/*
 * lineread reads from the Pascal text file with iorec pointer filep
 * into buffer[0], buffer[1],..., buffer[limit-1] (and
 * setting "limit").
 * Characters are read until a newline is found (which isn't put in the
 * buffer) or until the next character would go into buffer[BUF_SIZE].
 * And trailing blanks are to be ignored, so limit is really set to
 * one past the last non-blank.
 * 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)
	struct iorec	*filep;
{
	register int	c;
	register char	*cs;	/* pointer into buffer where next char goes */
	register char	*cnb;	/* last non-blank character input */
	register FILE	*iop;	/* stdio-style FILE pointer */
	register int	l;	/* how many chars before buffer overflow */

	iop = filep->fbuf;
	cnb = cs = &buffer[0];
	l = BUF_SIZE;

	/* overflow when next char would go into buffer[BUF_SIZE] */
	while ((--l >= 0) && ((c = getc(iop)) != EOF) && (c != '\n')) {
		if ((*cs++ = xord[c]) != ' ')
			cnb = cs;
	}

	if (c == EOF)
		filep->funit |= EOFF;	/* we hit end-of-file */

	limit = cnb - &buffer[0];
}

/*
 * linewrite writes to the Pascal text file with iorec pointer filep
 * from outbuf[0], outbuf[1],..., outbuf[cnt-1].
 * Translation is done, so that xchr[c] is output instead of c.
 */
linewrite(filep, cnt)
	struct iorec	*filep;
	int		cnt;
{
	register FILE	*iop;	/* stdio-style FILE pointer */
	register char	*cs;	/* pointer to next character to output */
	register int	l;	/* how many characters left to output */

	iop = filep->fbuf;
	cs = &outbuf[0];
	l = cnt;

	while (--l >= 0)
		putc(xchr[*cs++], iop);
}

/*
 *	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);
			}
		}
}

flush(filep)
	register struct iorec	*filep;
{
	if (filep->funit & FWRITE)
		fflush(filep->fbuf);
}
SHAR_EOF
cat << \SHAR_EOF > tangext.SYS_V.h
procedure exit(x : integer);
 external C;
procedure flush(var f: textfile);
 external C;
procedure lineread(var f:textfile);
 external C;
procedure linewrite(var f:textfile; cnt:integer);
 external C;
function testeof(var f:textfile):boolean;
 external C;
SHAR_EOF
cat << \SHAR_EOF > tftoplext.SYS_V.c
/* Copyright (c) 1979 Regents of the University of California */

static char sccsid[] = "@(#)PUT.c 1.3 6/10/81";

#include "h00vars.h"

short
byteread(curfile)
	register struct iorec	*curfile;
{
	register short i;

	if (curfile->funit & FWRITE) {
		ERROR("%s: Attempt to read, but open for writing\n",
			curfile->fname);
		return(-1);
	}
	if (curfile->funit & EOFF)
		ERROR("%s: Tried to read past end of file\n", curfile->fname);
	if (curfile->funit & SYNC) {
		i = getc(curfile->fbuf);
		if (ferror(curfile->fbuf)) {
			ERROR("%s: Tried to read past end of file\n", curfile->fname);
			return(-1);
		}
		if (feof(curfile->fbuf))
			curfile->funit |= EOFF;
	} else {
		i = *(unsigned char *)curfile->fileptr;
	}
	curfile->funit |= SYNC;
	return(i);
}
SHAR_EOF
cat << \SHAR_EOF > tftoplext.SYS_V.h
function byteread(var f: bytefile): byte; external C;
SHAR_EOF
cat << \SHAR_EOF > weavext.BSD4_n.c
/* External procedures for weave */
/*   Written by: H. Trickey, 11/17/83   */

/* Note: these procedures aren't necessary; the default input_ln and
 * flush_buffer routines in tangle/weave work fine on UNIX.
 * However a very big time improvement is acheived by using these.
 *
 * These procedures are the same as for tangle, except for a slight offset
 * in which characters are output from outbuf in linewrite.
 */

#define BUF_SIZE 100		/* should agree with tangle.web */

#include "h00vars.h"		/* defines Pascal I/O structure */

extern char buffer[];		/* 0..BUF_SIZE.  Input goes here */
extern char outbuf[];		/* 0..OUT_BUF_SIZE. Output from here */
extern char xord[],xchr[];	/* character translation arrays */
extern short limit;		/* index into buffer.  Note that limit
				   is 0..long_buf_size in weave.web which
				   differs from the definition in tangle.web */

/*
 * lineread reads from the Pascal text file with iorec pointer filep
 * into buffer[0], buffer[1],..., buffer[limit-1] (and
 * setting "limit").
 * Characters are read until a newline is found (which isn't put in the
 * buffer) or until the next character would go into buffer[BUF_SIZE].
 * And trailing blanks are to be ignored, so limit is really set to
 * one past the last non-blank.
 * 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)
struct iorec *filep;
{
	register c;
	register char *cs; /* pointer into buffer where next char goes */
	register char *cnb; /* last non-blank character input */
	register FILE *iop; /* stdio-style FILE pointer */
	register int l; /* how many chars allowed before buffer overflow */
	
	iop = filep->fbuf;
	cnb = cs = &(buffer[0]);
	l = BUF_SIZE;
	  /* overflow when next char would go into buffer[BUF_SIZE] */
	while (--l>=0 && (c = getc(iop)) != EOF && c!='\n')
	    if((*cs++ = xord[c])!=' ') cnb = cs;
	if (c == EOF)
	    filep->funit |= EOFF; /* we hit end-of-file */
	limit = cnb-&(buffer[0]);
}

/*
 * linewrite writes to the Pascal text file with iorec pointer filep
 * from outbuf[1], outbuf[1],..., outbuf[cnt].
 * (Note the offset of indices vis a vis the tangext version of this.)
 * Translation is done, so that xchr[c] is output instead of c.
 */
 linewrite(filep,cnt)
 struct iorec *filep;
 int cnt;
 {
 	register FILE *iop; /* stdio-style FILE pointer */
	register char *cs; /* pointer to next character to output */
	register int l; /* how many characters left to output */
	
	iop = filep->fbuf;
	cs = &(outbuf[1]);
	l = cnt;
	while (--l>=0) putc(xchr[*cs++],iop);
}
	
/*
**	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);
			}
	}
}
SHAR_EOF
cat << \SHAR_EOF > weavext.SYS_V.c
/* External procedures for weave */
/*   Written by: H. Trickey, 11/17/83   */

/* Note: these procedures aren't necessary; the default input_ln and
 * flush_buffer routines in tangle/weave work fine on UNIX.
 * However a very big time improvement is acheived by using these.
 *
 * These procedures are the same as for tangle, except for a slight offset
 * in which characters are output from outbuf in linewrite.
 */

#define BUF_SIZE 100		/* should agree with tangle.web */

#include "h00vars.h"		/* defines Pascal I/O structure */

extern char buffer[];		/* 0..BUF_SIZE.  Input goes here */
extern char outbuf[];		/* 0..OUT_BUF_SIZE. Output from here */
extern char xord[],xchr[];	/* character translation arrays */
extern short limit;		/* index into buffer.  Note that limit
				   is 0..long_buf_size in weave.web which
				   differs from the definition in tangle.web */

/*
 * lineread reads from the Pascal text file with iorec pointer filep
 * into buffer[0], buffer[1],..., buffer[limit-1] (and
 * setting "limit").
 * Characters are read until a newline is found (which isn't put in the
 * buffer) or until the next character would go into buffer[BUF_SIZE].
 * And trailing blanks are to be ignored, so limit is really set to
 * one past the last non-blank.
 * 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)
struct iorec *filep;
{
	register c;
	register char *cs; /* pointer into buffer where next char goes */
	register char *cnb; /* last non-blank character input */
	register FILE *iop; /* stdio-style FILE pointer */
	register int l; /* how many chars allowed before buffer overflow */
	
	iop = filep->fbuf;
	cnb = cs = &(buffer[0]);
	l = BUF_SIZE;
	  /* overflow when next char would go into buffer[BUF_SIZE] */
	while (--l>=0 && (c = getc(iop)) != EOF && c!='\n')
	    if((*cs++ = xord[c])!=' ') cnb = cs;
	if (c == EOF)
	    filep->funit |= EOFF; /* we hit end-of-file */
	limit = cnb-&(buffer[0]);
}

/*
 * linewrite writes to the Pascal text file with iorec pointer filep
 * from outbuf[1], outbuf[1],..., outbuf[cnt].
 * (Note the offset of indices vis a vis the tangext version of this.)
 * Translation is done, so that xchr[c] is output instead of c.
 */
 linewrite(filep,cnt)
 struct iorec *filep;
 int cnt;
 {
 	register FILE *iop; /* stdio-style FILE pointer */
	register char *cs; /* pointer to next character to output */
	register int l; /* how many characters left to output */
	
	iop = filep->fbuf;
	cs = &(outbuf[1]);
	l = cnt;
	while (--l>=0) putc(xchr[*cs++],iop);
}
	
/*
**	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);
			}
	}
}

flush(filep)
	register struct iorec	*filep;
{
	if (filep->funit & FWRITE)
		fflush(filep->fbuf);
}
SHAR_EOF
#	End of shell archive
exit 0